From 12bbd1e7dc48450790bcfb41a31fa2db42cfb8a0 Mon Sep 17 00:00:00 2001 From: Oleksandr Shyshatskyi Date: Sun, 23 Aug 2026 22:15:07 +0300 Subject: [PATCH] Retire the probe profile: there is one package now The probe profile was a bring-up aid. It set BUILD_APPLY=0, reinstalled the stock component byte-for-byte and wrote a report to the stick, so you could prove the update chain worked on your own machine -- the filename glob, the DES3 key, the md5 gate, run.sh execution -- before flashing anything that changed a file. That rehearsal has served its purpose. With it gone there was exactly one profile left, so the whole PROFILE indirection goes too: profiles/ is deleted and its six BUILD_* flags are plain defaults in bin/common.sh, which also means config.env now overrides them instead of being silently overridden. make default folds into make build; all-profiles and RECOVERY_PROFILE are gone with it. What is NOT gone is the undo button: flashing the stock FlashForge package still restores every file the mod touches, and case-recovery.sh still proves it. What is gone is the dry run. Note the loss: PROG_MB/DATA_MB used to come out of the probe report. The docs now point at df -h over ssh, which you only have after a successful flash. --- .github/workflows/ci.yml | 1 - .github/workflows/release.yml | 11 +---- Makefile | 56 ++++++++++------------- README.md | 6 +-- bin/build.sh | 11 ++--- bin/common.sh | 36 +++++++++------ bin/patch.sh | 71 +++++++++-------------------- bin/verify.sh | 8 ++-- docs/building.md | 64 +++++++++++--------------- docs/hardware-testing.md | 44 ++++-------------- docs/printer-replica.md | 2 +- docs/testing.md | 9 ++-- payload/report.sh | 85 ----------------------------------- profiles/default.env | 24 ---------- profiles/probe.env | 23 ---------- test.env.example | 2 +- test/lint-danger.sh | 3 +- test/printer/assemble.sh | 6 +-- test/printer/seed-prog.sh | 2 +- test/run-tests.sh | 47 +++++++------------ test/test-ash-conformance.sh | 2 +- 21 files changed, 143 insertions(+), 370 deletions(-) delete mode 100644 payload/report.sh delete mode 100644 profiles/default.env delete mode 100644 profiles/probe.env diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9c58d53..f85094e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -132,7 +132,6 @@ jobs: STOCK_TGZ_CREATOR5="$PWD/stock/Creator5-stock.tgz" STOCK_TGZ="" KLIPPER_FORK="" - DEFAULT_PROFILE=probe ROOT_PW_HASH='\$6\$ci\$abcdefghijklmnopqrstuvwxyz' FF_KEY='FFP0331&*%root' CFG diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6b98c83..e63b987 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,12 +25,6 @@ on: push: tags: [ 'v*' ] workflow_dispatch: - inputs: - profile: - description: 'Profile to build' - default: default - type: choice - options: [ default, probe ] permissions: contents: write @@ -38,8 +32,6 @@ permissions: jobs: release: runs-on: ubuntu-latest - env: - PROFILE: ${{ inputs.profile || 'default' }} steps: - uses: actions/checkout@v4 @@ -107,7 +99,6 @@ jobs: STOCK_TGZ_CREATOR5="$PWD/stock/Creator5-stock.tgz" STOCK_TGZ="" KLIPPER_FORK="" - DEFAULT_PROFILE=$PROFILE ROOT_PW_HASH='${{ secrets.ROOT_PW_HASH }}' FF_KEY='FFP0331&*%root' CFG @@ -125,7 +116,7 @@ jobs: creator5-fw-build ./test/run-tests.sh - name: Build both models - run: make release PROFILE=$PROFILE ASSET_ROOT=$PWD + run: make release ASSET_ROOT=$PWD - name: End-to-end update test on the packages that will actually ship # The suite above tested a package built from the same tree; this diff --git a/Makefile b/Makefile index 992ac44..38cb4b9 100644 --- a/Makefile +++ b/Makefile @@ -4,14 +4,12 @@ # inside the pinned build image (docker/Dockerfile.build); the docker socket # is mounted through so the simulation targets can start sibling containers. # -# make probe build the pre-flight package (changes nothing) -# make default build the firmware package +# make build build the firmware package # make test full brick-safety suite # make shell interactive shell in the build container # # Escape hatch: LOCAL=1 make runs the scripts directly on the host. -PROFILE ?= default # Packages carry only the software component by default: the stock installer # skips absent components, so the kernel and the MCU/board firmware are left # alone. FULL=1 carries all four (and reflashes the MCU). @@ -31,7 +29,7 @@ DOCKER_SOCK := /var/run/docker.sock # directories. Keeping the path identical on both sides avoids that entirely. # config.env usually points at a stock package OUTSIDE this repo, so the # directory holding it must be mounted too. Override when yours lives -# elsewhere: make ASSET_ROOT=/path/to/parent default +# elsewhere: make ASSET_ROOT=/path/to/parent build ASSET_ROOT ?= $(firstword $(wildcard /mnt/c /Users /home)) # Two runners, because the two lanes need different things: @@ -45,7 +43,7 @@ ASSET_ROOT ?= $(firstword $(wildcard /mnt/c /Users /home)) DOCKER_BASE = $(DOCKER) run --rm -i \ -v "$(CURDIR)":"$(CURDIR)" -w "$(CURDIR)" \ $(if $(ASSET_ROOT),-v "$(ASSET_ROOT)":"$(ASSET_ROOT)",) \ - -e PROFILE -e MODEL -e TARGET_MACHINE -e CONFIG_ENV -e ALLOW_STALE_CHELPER + -e MODEL -e TARGET_MACHINE -e CONFIG_ENV -e ALLOW_STALE_CHELPER ifeq ($(LOCAL),) RUN = $(DOCKER_BASE) $(IMAGE) @@ -62,23 +60,21 @@ else endif .DEFAULT_GOAL := help -.PHONY: help image shell build vendor probe default all-profiles \ +.PHONY: help image shell build vendor \ rootfs verify test test-lint test-install test-applets \ printer-image printer-image-push \ - test-recovery test-ui test-mcu test-ash test-abi test-chelper test-macros test-chamber test-model release clean distclean + test-recovery test-ui test-mcu test-ash test-abi test-chelper test-macros test-chamber test-basecfg test-model release clean distclean help: @echo 'creator5-custom-firmware -- everything runs in Docker' @echo - @echo 'Build (flash these in order -- see docs/hardware-testing.md):' - @echo ' make probe pre-flight changes nothing, reports back on a USB stick' - @echo ' make default the firmware Klipper fork, toolchanger, Mainsail,' + @echo 'Build (see docs/hardware-testing.md before you flash):' + @echo ' make build the firmware Klipper fork, toolchanger, Mainsail,' @echo ' ssh and HelixScreen' - @echo ' make all-profiles' - @echo ' make release PROFILE=

build BOTH models into dist/' + @echo ' make release build BOTH models into dist/' @echo @echo 'Models: packages are model-specific and refuse to install on the' - @echo 'other one. MODEL=Creator5 make default builds the non-Pro variant.' + @echo 'other one. MODEL=Creator5 make build builds the non-Pro variant.' @echo @echo 'Recovery: keep a copy of the STOCK FlashForge .tgz on a spare stick.' @echo 'Flashing it restores every file the mod touches (see make test-recovery).' @@ -97,6 +93,7 @@ help: @echo ' make test-chelper c_helper.so exports everything klippy declares' @echo ' make test-macros the ff-*.cfg gcode macros parse as Jinja' @echo ' make test-chamber the chamber heater is off on the Creator 5' + @echo ' make test-basecfg our printer.base.cfg still matches the stock one' @echo @echo 'test-install, test-recovery, test-ui, test-mcu and test-ash run inside' @echo 'a replica of the printer: the real rootfs.squashfs under qemu-mipsel, with' @@ -131,33 +128,26 @@ shell: image @$(RUNTTY) bash # =========================================================================== -# BUILD LANE -- produces the package you flash. Reads config.env + profiles/, -# ships payload/ and assets/, and touches nothing under test/. +# BUILD LANE -- produces the package you flash. Reads config.env, ships +# payload/ and assets/, and touches nothing under test/. # =========================================================================== # Mainsail and HelixScreen are not vendored in the repo. bin/build.sh fetches -# whatever the profile needs; this target pre-fetches everything, and is a +# what the build needs; this target pre-fetches everything, and is a # no-op once vendor/ holds files with the sha256 that versions.env pins. vendor: image config.env @$(RUN) ./bin/fetch-assets.sh --all build: image config.env - @PROFILE=$(PROFILE) $(RUN) ./bin/build.sh $(PACKARGS) - -probe default: image config.env - @PROFILE=$@ $(RUN) ./bin/build.sh $(PACKARGS) - -all-profiles: image config.env - @for p in probe default; do \ - echo "=== $$p ==="; PROFILE=$$p $(RUN) ./bin/build.sh || exit 1; done + @$(RUN) ./bin/build.sh $(PACKARGS) # One package per model, collected in dist/. They cannot share content: the # two stock packages ship different firmwareExe binaries. release: image config.env @rm -rf dist && mkdir -p dist @for m in Creator5Pro Creator5; do \ - echo "=== $$m / $(PROFILE) ==="; \ - MODEL=$$m PROFILE=$(PROFILE) $(RUN) ./bin/build.sh $(PACKARGS) || exit 1; \ + echo "=== $$m ==="; \ + MODEL=$$m $(RUN) ./bin/build.sh $(PACKARGS) || exit 1; \ MODEL=$$m $(RUN) ./bin/verify.sh || exit 1; \ cp work/out/$$m-*.tgz dist/ || exit 1; \ done @@ -223,6 +213,9 @@ test-macros: image test-chamber: image @$(RUN) python3 ./test/test-chamber.py +test-basecfg: image + @$(RUN) python3 ./test/test-base-cfg.py + test-applets: image @$(RUN) python3 ./test/test-applets.py @@ -237,22 +230,21 @@ test-mcu: image # there). Look in both. test-install: image @$(RUNSIM) bash -c 'pkg=$$(ls -1 dist/$(or $(MODEL),Creator5Pro)-*.tgz work/out/$(or $(MODEL),Creator5Pro)-*.tgz 2>/dev/null | head -1); \ - [ -n "$$pkg" ] || { echo "build a package first: make default (or make release)"; exit 1; }; \ + [ -n "$$pkg" ] || { echo "build a package first: make build (or make release)"; exit 1; }; \ echo "package: $$pkg"; ./test/sim-install.sh "$$pkg"' # Recovery = flash the stock package you already have. This proves it works. # # It builds its own package rather than reusing whatever is lying around: the -# test is meaningless against a profile that does not replace the UI, and -# `probe` deliberately does not. RECOVERY_PROFILE=

to test another one. -RECOVERY_PROFILE ?= default +# test is only meaningful against a package that really does replace the UI, +# and whatever is in work/out may be anything. test-recovery: image config.env - @MODEL=$(or $(MODEL),Creator5Pro) PROFILE=$(RECOVERY_PROFILE) $(RUNSIM) bash -c '. ./bin/common.sh; \ + @MODEL=$(or $(MODEL),Creator5Pro) $(RUNSIM) bash -c '. ./bin/common.sh; \ ./bin/build.sh $(PACKARGS) >/dev/null || exit 1; \ m=$$(ls -1 work/out/$$TARGET_MACHINE-*.tgz 2>/dev/null | head -1); \ [ -n "$$m" ] || { echo "no package built for $$TARGET_MACHINE"; exit 1; }; \ [ -f "$$STOCK_TGZ" ] || { echo "no stock package for $$TARGET_MACHINE"; exit 1; }; \ - echo "mod: $$m ($(RECOVERY_PROFILE))"; echo "stock: $$STOCK_TGZ"; \ + echo "mod: $$m"; echo "stock: $$STOCK_TGZ"; \ ./test/sim-roundtrip.sh "$$m" "$$STOCK_TGZ"' clean: diff --git a/README.md b/README.md index 228ee4c..1ae43df 100644 --- a/README.md +++ b/README.md @@ -74,10 +74,10 @@ Not sure which you have? On the printer: **Settings → About**. Afterwards, `http:///` gets you Mainsail. The install log is on the printer at `/usr/data/anvil-install.log`. -### Before you do +### Two things to do first -One file per model, one flash — but do two things first, because they are the -cheap version of every problem people hit: +One file per model, one flash — but do these before you start, because they +are the cheap version of every problem people hit: * **Check the model.** A `Creator5Pro-` package will not install on a Creator 5 and vice versa; the printer refuses it outright, which is annoying rather diff --git a/bin/build.sh b/bin/build.sh index 433a9e2..f0b8b40 100644 --- a/bin/build.sh +++ b/bin/build.sh @@ -1,14 +1,9 @@ #!/usr/bin/env bash -# One-shot: fetch -> unpack -> patch -> pack, for one profile. +# One-shot: fetch -> unpack -> patch -> pack. # -# ./bin/build.sh the profile from config.env (DEFAULT_PROFILE) -# ./bin/build.sh probe pre-flight: changes nothing -# ./bin/build.sh default --slim pass-through options go to pack.sh +# ./bin/build.sh build the package +# ./bin/build.sh --slim options are passed through to pack.sh set -euo pipefail -case "${1:-}" in - ''|-*) : ;; - *) export PROFILE="$1"; shift ;; -esac D="$(dirname "$0")" "$D/fetch-assets.sh" "$D/unpack.sh" diff --git a/bin/common.sh b/bin/common.sh index 8d1f49f..1374021 100644 --- a/bin/common.sh +++ b/bin/common.sh @@ -1,10 +1,5 @@ # Sourced by every script in bin/. Resolves the repo root, loads config.env -# and the selected profile, and exports the feature flags. -# -# Profile selection, in order of precedence: -# PROFILE=probe ./bin/build.sh environment -# ./bin/build.sh --profile probe argument (parsed by the caller) -# PROFILE in config.env default +# and exports the feature flags. ROOT="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")/.." && pwd)" cd "$ROOT" @@ -21,14 +16,27 @@ fi # shellcheck disable=SC1090 . "$CONFIG_ENV" -PROFILE="${PROFILE:-${DEFAULT_PROFILE:-default}}" -if [ -f "profiles/$PROFILE.env" ]; then - # shellcheck disable=SC1090 - . "profiles/$PROFILE.env" -else - echo "unknown profile '$PROFILE' (have: $(ls profiles/*.env 2>/dev/null | xargs -n1 basename 2>/dev/null | sed 's/\.env$//' | tr '\n' ' '))" >&2 - exit 1 -fi +# WHAT GOES INTO THE PACKAGE. There is exactly one build -- the firmware: +# forked Klipper with toolchanger support, Mainsail/Moonraker, ssh, and +# HelixScreen driving the touchscreen in place of FlashForge's UI. +# +# These used to live in profiles/*.env, chosen by a PROFILE variable, back +# when a second "changes nothing, writes a report" package existed alongside +# this one. With one build left the indirection bought nothing but a layer to +# read through, so the flags are plain defaults here and config.env -- sourced +# above -- still overrides any of them. +# +# FlashForge's firmwareExe is REPLACED, not kept: HelixScreen is the only UI. +# If it crash-loops, S80ui latches SAFE-MODE after 3 failed boots and the +# printer boots headless instead of looping. ssh and Mainsail are your +# recovery path if the screen is dark, and a USB stick with the STOCK +# FlashForge package on it is the uninstall (proven by `make test-recovery`). +BUILD_KLIPPER="${BUILD_KLIPPER:-fork}" +BUILD_TOOLCHANGE="${BUILD_TOOLCHANGE:-1}" +BUILD_MAINSAIL="${BUILD_MAINSAIL:-1}" +BUILD_HELIX="${BUILD_HELIX:-1}" +MOD_SSH="${MOD_SSH:-1}" +MOD_WEB="${MOD_WEB:-1}" # Third-party payload pieces (Mainsail, HelixScreen). They are downloaded on # demand rather than vendored, so the repo carries no binaries and no binary diff --git a/bin/patch.sh b/bin/patch.sh index 59f394a..36b55b5 100644 --- a/bin/patch.sh +++ b/bin/patch.sh @@ -7,9 +7,6 @@ set -euo pipefail SW=work/software [ -d "$SW" ] || { echo "run bin/unpack.sh first" >&2; exit 1; } -echo "profile: $PROFILE -- ${PROFILE_DESC:-}" -echo - MARK_BEGIN="# >>> anvil begin >>>" MARK_END="# <<< anvil end <<<" @@ -29,35 +26,6 @@ MP=work/modpayload rm -rf "$MP" "$SW/mod" # $SW/mod: leftover from an older layout mkdir -p "$MP/bin" "$MP/nginx" "$MP/www" "$MP/config" -# --------------------------------------------------------------------------- -# BUILD_APPLY=0 (the "probe" profile): reinstall the stock component untouched -# and add only a diagnostic report. Nothing on the printer changes. -# --------------------------------------------------------------------------- -if [ "${BUILD_APPLY:-1}" = "0" ]; then - say "BUILD_APPLY=0 -- stock component left byte-for-byte unmodified" - if [ "${BUILD_REPORT:-0}" = "1" ]; then - say "adding diagnostic report step" - python3 - "$SW/run.sh" payload/report.sh <<'PY2' -import sys, re -run, extra = sys.argv[1], sys.argv[2] -B, E = "# >>> anvil begin >>>", "# <<< anvil end <<<" -s = open(run, encoding='utf-8', errors='surrogateescape').read() -s = re.sub(re.escape(B) + r".*?" + re.escape(E) + r"\n?", "", s, flags=re.S) -block = open(extra, encoding='utf-8').read() -m = list(re.finditer(r"^exit 0\s*$", s, flags=re.M)) -i = m[-1].start() if m else len(s) -s = s[:i] + B + "\n" + block + E + "\n\n" + s[i:] -open(run, 'w', encoding='utf-8', errors='surrogateescape').write(s) -PY2 - fi - rm -rf "$MP" - echo - echo "Patched (probe profile -- no changes to the printer)." - echo " software component: $(du -sh "$SW" | cut -f1)" - echo "Now run bin/pack.sh" - exit 0 -fi - # ---------------------------------------------------------------- 1. Klipper if [ "${BUILD_KLIPPER:-fork}" = "fork" ] && [ -d "${KLIPPER_FORK:-}/klippy" ]; then say "Klipper: installing fork tree from $KLIPPER_FORK" @@ -126,22 +94,34 @@ if [ "${BUILD_TOOLCHANGE:-1}" = "1" ]; then # .cfg files belong on the data partition; run.sh installs them without # clobbering a config the user already tuned. cp -f payload/klipper/config/ff-*.cfg "$MP/config/" + # Our printer.base.cfg is FlashForge's with the chamber block replaced by + # [include printer.chamber.cfg] -- Klipper can override an option but + # cannot un-declare a section, and the plain Creator 5 has no chamber + # heating element, so its heater has to be absent rather than neutralised. + # test/test-base-cfg.py reconstructs the stock file from ours plus the + # Pro's chamber file and fails if FlashForge's has changed. + cp -f payload/klipper/config/printer.base.cfg "$SW/klipper/config/printer.base.cfg" + # Anything that differs between models exists once per model, named # .creator5 / .creator5pro, and the matching one is installed # under its real name. Nothing is edited: the suffixed file IS the - # difference. The suffixed names do not match the ff-*.cfg glob above, so - # a variant cannot leak into the wrong package. + # difference. printer.*.cfg belongs beside printer.base.cfg on the program + # partition; ff-*.cfg belongs on the data partition with the rest. SUFFIX=$(printf '%s' "$TARGET_MACHINE" | tr 'A-Z' 'a-z') for variant in payload/klipper/config/*."$SUFFIX"; do [ -e "$variant" ] || continue - cp -f "$variant" "$MP/config/$(basename "$variant" ".$SUFFIX")" - say "Model: $(basename "$variant" ".$SUFFIX") for $TARGET_MACHINE" + base=$(basename "$variant" ".$SUFFIX") + case "$base" in + printer.*) dest="$SW/klipper/config/$base" ;; + *) dest="$MP/config/$base" ;; + esac + cp -f "$variant" "$dest" + say "Model: $base for $TARGET_MACHINE" done - # ff-model.cfg is what tells ff-chamber.cfg whether this machine has a - # chamber heater. Missing, every macro that reads it fails at runtime, so - # this is a broken build rather than a silent default. - [ -f "$MP/config/ff-model.cfg" ] \ - || { echo "no ff-model.cfg.$SUFFIX for TARGET_MACHINE=$TARGET_MACHINE" >&2; exit 1; } + # printer.base.cfg includes it unconditionally, so without it klippy will + # not start at all. A broken build, not a silent default. + [ -f "$SW/klipper/config/printer.chamber.cfg" ] \ + || { echo "no printer.chamber.cfg.$SUFFIX for TARGET_MACHINE=$TARGET_MACHINE" >&2; exit 1; } else skip "Toolchange" fi @@ -241,16 +221,13 @@ mkdir -p "$MP/init.d" cp -f payload/init.d/S* "$MP/init.d/" chmod +x "$MP/init.d"/S* sed -e "s/^MOD_WEB=.*/MOD_WEB=${MOD_WEB:-1}/" \ + -e "s/^MOD_CAM=.*/MOD_CAM=${MOD_CAM:-1}/" \ -e "s/^MOD_SSH=.*/MOD_SSH=${MOD_SSH:-1}/" \ -e "s/^MOD_WIFI=.*/MOD_WIFI=${MOD_WIFI:-1}/" \ payload/anvil.conf > "$MP/anvil.conf" # --------------------------------------------------- 10. run.sh install step say "run.sh: injecting mod install blocks (pre + post)" -# The diagnostic report is a DEBUG payload: report.sh copies /etc, passwd and -# shadow onto the USB stick. Only the probe profile turns it on -- see -# profiles/*.env. It rides at the end of the post block rather than in one of -# its own, so there is still exactly one injected region to strip on re-run. POST=work/.run-post.sh # 1 only when ssh is on and nothing was baked in: a package is one file that # many people flash, so a baked-in default would be the same password on every @@ -263,10 +240,6 @@ else fi sed -e "s/^MOD_PW_AUTO=.*/MOD_PW_AUTO=$PW_AUTO/" \ payload/run-append.sh > "$POST" -if [ "${BUILD_REPORT:-0}" = "1" ]; then - say "run.sh: including the diagnostic report step (BUILD_REPORT=1)" - cat payload/report.sh >> "$POST" -fi python3 - "$SW/run.sh" payload/run-pre.sh "$POST" <<'PY' import sys, re run, pre_f, post_f = sys.argv[1], sys.argv[2], sys.argv[3] diff --git a/bin/verify.sh b/bin/verify.sh index 6bc5b59..e8a754e 100644 --- a/bin/verify.sh +++ b/bin/verify.sh @@ -160,8 +160,8 @@ if [ -n "$FN_MACHINE" ]; then fi # 10 --------------------------------------------------- the ship boundary -# Only payload/ and assets/ may end up on a printer; bin/, test/, docker/ and -# profiles/ are host-side. Nothing enforces that except this check. +# Only payload/ and assets/ may end up on a printer; bin/, test/ and docker/ +# are host-side. Nothing enforces that except this check. # # It compares by CONTENT, not by name: a name blacklist would trip over any # file Mainsail or HelixScreen happens to call common.sh, while a byte-for-byte @@ -173,13 +173,13 @@ if [ -f "$T/anvil.tar.xz" ]; then xz -dc "$T/anvil.tar.xz" 2>/dev/null | tar -xf - -C "$T/ship/.anvil" 2>/dev/null \ || tar -xf "$T/anvil.tar.xz" -C "$T/ship/.anvil" 2>/dev/null || true fi -find bin test docker profiles -type f 2>/dev/null | xargs -r md5sum 2>/dev/null \ +find bin test docker -type f 2>/dev/null | xargs -r md5sum 2>/dev/null \ | awk '{print $1}' | sort -u > "$T/host.md5" find "$T/ship" -type f 2>/dev/null | xargs -r md5sum 2>/dev/null > "$T/ship.md5" LEAK=$(awk 'NR==FNR{h[$1];next} $1 in h {print}' "$T/host.md5" "$T/ship.md5" \ | sed "s|$T/ship/||") if [ -z "$LEAK" ]; then - ok "package carries nothing from bin/, test/, docker/ or profiles/" + ok "package carries nothing from bin/, test/ or docker/" else bad "host-side files leaked into the package:" echo "$LEAK" | head -10 | sed 's/^/ /' diff --git a/docs/building.md b/docs/building.md index a3d68fc..83289fd 100644 --- a/docs/building.md +++ b/docs/building.md @@ -6,12 +6,11 @@ it, it does not replace it. Everything else is Docker. ```sh cp config.env.example config.env # what to build, and what ships $EDITOR config.env # point it at your stock package -make probe # pre-flight: changes nothing, reports back -make default # the firmware +make build # the firmware ``` -The package lands in `work/out/`. `make release PROFILE=

` builds both -models into `dist/`. +The package lands in `work/out/`. `make release` builds both models into +`dist/`. ## Requirements @@ -41,31 +40,27 @@ MCU/board firmware are left untouched — MCU flashing is the riskiest thing in a package and there is no reason to run it for a userspace mod. `FULL=1 make ` carries all four. -## Profiles +## One build -There are two, and only two. `profiles/*.env` set the `BUILD_*` flags: +There is one package: the forked Klipper with toolchanger support, +Mainsail/Moonraker, ssh, and HelixScreen as the UI. `bin/common.sh` defaults +the `BUILD_*` flags to exactly that, and `config.env` can override any of +them if you want a piece left out. -| Profile | Klipper | Mainsail | HelixScreen | ssh | Report | -|---|---|---|---|---|---| -| `probe` | stock | – | – | – | ✓ | -| `default` | fork | ✓ | ✓ (as the UI) | ✓ | – | - -`probe` is a pre-flight check: it reinstalls the stock software byte-for-byte -and writes a diagnostic report to the USB stick, proving the update chain -works on *your* machine before anything changes. `default` is the firmware. - -There used to be five profiles — `ssh`, `web`, `full` and `helix` climbing one -feature at a time. They are collapsed into `default`: the intermediate rungs -each needed their own flash-and-verify cycle, and the recovery story is the -same at every rung (flash the stock package), so the extra loops bought -caution nobody was spending. +There used to be a `profiles/` directory choosing between builds — five of +them at one point (`ssh`, `web`, `full`, `helix`) climbing one feature at a +time, then two (`probe`, `default`). The intermediate rungs each cost their +own flash-and-verify cycle while the recovery story stayed the same at every +one of them (flash the stock package), so they bought caution nobody was +spending; the last of them, `probe`, changed nothing on the printer and only +wrote a diagnostic report to the USB stick, which was a bring-up aid rather +than something to keep shipping. With one build left, the selection layer went +with them. ```sh -make probe # pre-flight -make default # the firmware -make all-profiles # both -make release PROFILE=default # both models, into dist/ -MODEL=Creator5 make default # just the non-Pro +make build # the firmware +make release # both models, into dist/ +MODEL=Creator5 make build # just the non-Pro ``` ## Two kinds of flag @@ -73,18 +68,13 @@ MODEL=Creator5 make default # just the non-Pro This distinction is the one to keep straight: * **`BUILD_*`** decides what goes *into* a package. Read at build time only, - owned by `profiles/*.env`, never present on the printer. - (`BUILD_APPLY`, `BUILD_REPORT`, `BUILD_KLIPPER`, `BUILD_TOOLCHANGE`, - `BUILD_MAINSAIL`, `BUILD_HELIX`.) + defaulted in `bin/common.sh`, never present on the printer. + (`BUILD_KLIPPER`, `BUILD_TOOLCHANGE`, `BUILD_MAINSAIL`, `BUILD_HELIX`.) * **`MOD_*`** are runtime switches. They are written into `/usr/data/anvil/anvil.conf`, which the printer re-reads at every boot, so they can be changed over ssh afterwards and survive a mod update. (`MOD_WEB`, `MOD_SSH`, `MOD_WIFI`.) -`BUILD_REPORT` is the diagnostic report, and it is a debug payload: -`payload/report.sh` copies `/etc`, `passwd` and `shadow` onto the USB stick. -Only the `probe` profile turns it on. - ## Third-party pieces are downloaded, not vendored Mainsail and the HelixScreen build for this printer are large binaries, so the @@ -108,8 +98,8 @@ Setting `MAINSAIL_ZIP` or `HELIX_TGZ` in `config.env` overrides the download and builds against your own local copy. An explicit path is used as-is and is never checksummed. -If a profile asks for Mainsail or HelixScreen and the file is not there, the -build fails. It used to skip silently, which shipped a package with an empty +If the build asks for Mainsail or HelixScreen and the file is not there, it +fails. It used to skip silently, which shipped a package with an empty web root and no way to notice. ## The root password @@ -156,7 +146,6 @@ payload/ POSIX sh, busybox ash -- runs ON the printer anvil.conf runtime switches, preserved across mod updates run-pre.sh backups, injected at the TOP of the stock run.sh run-append.sh payload install, injected before its exit - report.sh the pre-flight diagnostic (BUILD_REPORT=1 -- probe only) assets/ nginx.conf, moonraker.conf ``` @@ -164,7 +153,6 @@ assets/ nginx.conf, moonraker.conf ``` bin/ fetch-assets -> unpack -> patch -> pack, plus verify -profiles/ probe and default versions.env pinned Mainsail / HelixScreen versions + sha256 vendor/ where fetch-assets.sh caches them (gitignored) config.env your paths, the root password hash, the model @@ -185,8 +173,8 @@ docs/ the documentation Two things keep the boundary from eroding: only `payload/` and `assets/` are ever copied into a package by `patch.sh`, and `make verify` fails if a built -package contains any file byte-identical to one in `bin/`, `test/`, `docker/` -or `profiles/`. +package contains any file byte-identical to one in `bin/`, `test/` or +`docker/`. ## Rebuilding chelper diff --git a/docs/hardware-testing.md b/docs/hardware-testing.md index 83140e8..864a929 100644 --- a/docs/hardware-testing.md +++ b/docs/hardware-testing.md @@ -6,13 +6,13 @@ CI installs the package into a replica of the printer -- the real machine would still boot. What it cannot do is drive the screen, the MCUs, the toolchanger or a print. This is the on-hardware procedure. -There are two flashes: `probe`, which changes nothing and proves the update -chain works on your machine, and `default`, which is the firmware. +There is one flash: the firmware package for your model. -**Rule: do the probe first, and have the stock package on a spare stick before -you flash the firmware.** The probe costs five minutes and rules out a bad -stick, the wrong model or a truncated download — the three failures that are -annoying on a probe and frightening on a real flash. +**Rule: have the stock FlashForge package for your model on a spare stick +before you flash anything.** Flashing it back is the uninstall, and it is the +only recovery step that needs nothing but a USB port — no ssh, no screen. It +is proven by `make test-recovery`, which installs the mod into the printer +replica and then flashes the stock package over it. --- @@ -38,8 +38,8 @@ Find yours in Settings → About, or in `TARGET_MACHINE` in `config.env`. Then: ```sh -make default && make verify # one model -make release PROFILE=default # both, into dist/ +make build && make verify # one model +make release # both, into dist/ ``` `verify.sh` fails loudly on a mismatch. **You must start from a stock package @@ -65,33 +65,7 @@ boot script globs `Creator5Pro-*.tgz`, the non-Pro globs `Creator5-*.tgz`. --- -## Stage 0 — probe (`make probe`) - -**Changes nothing.** Reinstalls the stock software component byte-for-byte and -writes a diagnostic report to the USB stick. - -Flash it, wait for the reboot, pull the stick and read: - -| File on the stick | What it tells you | -|---|---| -| `anvil-report.txt` | free space, partitions, installed versions, init layout, whether nginx/moonraker really exist | -| `anvil-stock-etc.tar` | the whole `/etc`, so the init chain can be studied offline | -| `anvil-stock-nginx.conf` | the stock nginx config (not shipped in any update package) | -| `anvil-stock-bootscripts.tar` | `app_startup.sh`, `start.sh`, `passwd`, `shadow` as they exist on YOUR unit | - -**Go/no-go:** the report exists and the printer boots normally. -If the stick comes back empty, the package never installed — nothing was -changed, and you have learned that before risking anything. - -**Check in the report:** -- free space on `/usr/data` is comfortably above the size of your full package -- `moonrakerDmn: yes` and `nginx binary: yes` -- the `INIT SYSTEM` block matches expectations (busybox init, `/etc/init.d/rcS`, - `S50dropbear` present) - ---- - -## Stage 1 — the firmware (`make default`) +## The flash (`make build`) One flash brings up everything: a root password you know, Mainsail and moonraker, the forked Klipper with the toolchanger extras, and HelixScreen on diff --git a/docs/printer-replica.md b/docs/printer-replica.md index e48a823..243f3a8 100644 --- a/docs/printer-replica.md +++ b/docs/printer-replica.md @@ -187,7 +187,7 @@ logged instead. for presence, executability and ELF-ness, never run. * Timing-dependent boot races are not modelled. * Partition sizes are unbounded unless you set `PROG_MB` and `DATA_MB` (in `test.env`) from - the `df -h` block in the stage-0 probe report. Until then an install that + what `df -h` reports on the printer itself. Until then an install that runs the data partition out of space passes here and fails on the machine. The replica says so in `/usr/prog/.SIMULATED`. diff --git a/docs/testing.md b/docs/testing.md index 2852f1c..1c1269a 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -78,17 +78,16 @@ say where it goes — `run-tests.sh` stamps every header with elapsed seconds: ``` == brick-risk lint == [0s] -== profile: probe / default (on the fixture) == [1s] +== build on the fixture == [1s] == extracting the printer rootfs == [16s] == applets / ash / ABI / UI safety == [18s] -== end-to-end update on the replica: probe == [28s] -== end-to-end update on the replica: default == [111s] +== end-to-end update on the replica == [111s] == recovery: a stock package reverts the mod == [250s] [326s] ``` -What is left is real work: two full package builds (the `default` payload is -55MB through `xz`) and three replica runs. If it needs to get faster again, +What is left is real work: two full package builds (the payload is 55MB +through `xz`) and two replica runs. If it needs to get faster again, that is where to look — not in the harness. ## What was dropped, and why diff --git a/payload/report.sh b/payload/report.sh deleted file mode 100644 index 4f71c50..0000000 --- a/payload/report.sh +++ /dev/null @@ -1,85 +0,0 @@ -# Diagnostic report. Runs on the printer during install and writes everything -# we need to know to /mnt (the USB stick), which is still mounted at this -# point -- app_startup.sh unmounts it only after runFirmwareExe.sh returns. -# -# Read this BEFORE flashing anything that modifies the machine: it tells you -# the real partition sizes, what is already installed, and whether the whole -# decrypt -> md5 -> run.sh chain works on your unit. -REPORT=/mnt/anvil-report.txt -{ - echo "=== anvil report ===" - echo "date: `date 2>/dev/null`" - echo "machine: `uname -a`" - echo "args: $*" - echo - echo "--- free space (the number that decides what fits) ---" - df -h 2>/dev/null || df - echo - echo "--- mounts (a mount named like a mod blocks factory restore) ---" - mount - echo - echo "--- partitions ---" - /sbin/fdisk -l /dev/mmcblk0 2>/dev/null | head -30 - echo - echo "--- installed component versions ---" - for c in software library kernel control; do - echo " $c: `ls -1 /usr/prog/PROGRAM/$c 2>/dev/null | tr '\n' ' '`" - done - echo - echo "--- does the web stack really ship on stock? ---" - echo " nginx binary : `[ -x /usr/prog/nginx/sbin/nginx ] && echo yes || echo NO`" - echo " nginx conf : `[ -f /usr/prog/nginx/conf/nginx.conf ] && echo yes || echo NO`" - echo " moonraker : `[ -f /usr/prog/moonraker/moonraker/moonraker/moonraker.py ] && echo yes || echo NO`" - echo " moonrakerDmn : `[ -x /usr/prog/klipper/moonrakerDaemon ] && echo yes || echo NO`" - echo " python3 : `/usr/prog/Python-3.8.2/bin/python3 -V 2>&1`" - echo " xz : `command -v xz || echo NO`" - echo - echo "--- nginx.conf (needed to know the stock docroot/ports) ---" - cat /usr/prog/nginx/conf/nginx.conf 2>/dev/null | head -60 - echo - echo "--- INIT SYSTEM (decides how we should start services) ---" - echo " PID 1 : `cat /proc/1/comm 2>/dev/null` (`readlink /proc/1/exe 2>/dev/null`)" - echo " systemctl : `command -v systemctl || echo NO`" - echo " /etc/inittab : `[ -f /etc/inittab ] && echo yes || echo NO`" - echo " /etc/init.d : `[ -d /etc/init.d ] && echo yes || echo NO`" - echo " start-stop-daemon: `command -v start-stop-daemon || echo NO`" - echo - echo " ### /etc/inittab" - cat /etc/inittab 2>/dev/null - echo " ### ls /etc/init.d" - ls -la /etc/init.d 2>/dev/null - echo " ### /etc/init.d/rcS" - cat /etc/init.d/rcS 2>/dev/null | head -40 - echo " ### what invokes app_startup.sh" - grep -rl "app_startup" /etc /usr/prog/bin 2>/dev/null | head - grep -rn "app_startup" /etc/inittab /etc/init.d/* 2>/dev/null | head - echo - echo " ### running processes at install time" - ps 2>/dev/null | head -40 - echo - echo "--- klipper ---" - echo " chelper: `ls -l /usr/prog/klipper/klippy/chelper/c_helper.so 2>/dev/null`" - echo " extras : `ls -1 /usr/prog/klipper/klippy/extras 2>/dev/null | wc -l` modules" - echo - echo "--- existing config on the data partition ---" - ls -la /usr/data/config 2>/dev/null - echo - echo "--- stock boot scripts (so we can diff our patched versions) ---" - echo "### /usr/prog/app_startup.sh"; cat /usr/prog/app_startup.sh 2>/dev/null - echo "### /usr/prog/klipper/start.sh"; cat /usr/prog/klipper/start.sh 2>/dev/null - echo - echo "=== end of report ===" -} > "$REPORT" 2>&1 -sync - -# Copy the stock nginx conf out too -- we need it verbatim to build a correct -# Mainsail vhost, and it is not in any update package. -cp -f /usr/prog/nginx/conf/nginx.conf /mnt/anvil-stock-nginx.conf 2>/dev/null -# The whole /etc, so the init layout can be studied offline instead of -# guessed at. It is a few hundred KB and answers the init.d-vs-custom -# question definitively. -tar -cf /mnt/anvil-stock-etc.tar /etc 2>/dev/null -tar -cf /mnt/anvil-stock-bootscripts.tar \ - /usr/prog/app_startup.sh /usr/prog/klipper/start.sh \ - /usr/prog/etc/passwd /usr/prog/etc/shadow 2>/dev/null -sync diff --git a/profiles/default.env b/profiles/default.env deleted file mode 100644 index a0699bf..0000000 --- a/profiles/default.env +++ /dev/null @@ -1,24 +0,0 @@ -# THE DEFAULT PROFILE -- the actual firmware: everything, in one flash. -# -# Forked Klipper with toolchanger support, Mainsail/Moonraker, ssh, and -# HelixScreen driving the touchscreen in place of FlashForge's UI. -# -# Do not flash this until stage 0 (`make probe`) has come back clean on YOUR -# machine, and keep a USB stick with the STOCK FlashForge package within -# reach -- flashing that is the uninstall (proven by `make test-recovery`). -# -# FlashForge's firmwareExe is REPLACED, not kept: HelixScreen is the only UI. -# If it crash-loops, S80ui latches SAFE-MODE after 3 failed boots and the -# printer boots headless instead of looping. ssh and Mainsail are your -# recovery path if the screen is dark. -PROFILE_DESC="the firmware: forked Klipper + toolchanger + Mainsail + ssh + HelixScreen" - -BUILD_REPORT=0 # the report dumps /etc + shadow to the stick: probe only -BUILD_APPLY=1 - -BUILD_KLIPPER=fork -BUILD_TOOLCHANGE=1 -BUILD_MAINSAIL=1 -BUILD_HELIX=1 -MOD_SSH=1 -MOD_WEB=1 diff --git a/profiles/probe.env b/profiles/probe.env deleted file mode 100644 index 23e7613..0000000 --- a/profiles/probe.env +++ /dev/null @@ -1,23 +0,0 @@ -# STAGE 0 -- the first thing you should ever flash. -# -# Changes NOTHING on the printer. It reinstalls the stock software component -# byte-for-byte and adds one extra step: write a diagnostic report to the USB -# stick, then reboot. -# -# Purpose: prove the whole chain works on YOUR machine -- the filename glob, -# the DES3 key, the md5 gate, run.sh execution -- and learn the real partition -# sizes BEFORE you commit to a package that modifies anything. -# -# Pull the stick afterwards and read anvil-report.txt. -PROFILE_DESC="stage 0: no changes, writes a diagnostic report to the USB stick" - -BUILD_REPORT=1 # write the report -BUILD_APPLY=0 # master switch: change nothing at all - -BUILD_KLIPPER=stock -BUILD_TOOLCHANGE=0 -BUILD_MAINSAIL=0 -BUILD_HELIX=0 -MOD_SSH=0 -MOD_WEB=0 -ROOT_PW_HASH="" diff --git a/test.env.example b/test.env.example index 50b89d3..7d0f389 100644 --- a/test.env.example +++ b/test.env.example @@ -38,7 +38,7 @@ PRINTER_IMAGE="monstrofil/creator5-printer:latest" # https://github.com/ghzserg/FF/releases/download/R/Creator5Pro-factory.tar.xz PROG_DUMP="$HOME/Desktop/Creator5Pro-factory.tar.xz" -# Real partition sizes, from the `df -h` block of the stage-0 probe report. +# Real partition sizes, as `df -h` reports them on the printer itself. # Until these are set the replica's prog/data partitions are unbounded, so an # install that runs the machine out of space would pass here and fail there. PROG_MB="" diff --git a/test/lint-danger.sh b/test/lint-danger.sh index 7d2d6ba..e8ef162 100644 --- a/test/lint-danger.sh +++ b/test/lint-danger.sh @@ -42,7 +42,6 @@ while IFS= read -r f; do grep -nE 'rm[[:space:]]+-[a-zA-Z]*r[a-zA-Z]*[[:space:]]+\$[A-Za-z_]+/' "$f" | head -3 | sed 's/^/ /' fi # Replacing the init/boot chain without restoring a UI - # Only MODIFYING app_startup.sh is a risk; report.sh merely cats it. if grep -nE '(cp|mv|install|tee|sed[[:space:]]+-i|>>?[[:space:]]*)[^|;]*app_startup\.sh' "$f" >/dev/null \ && ! grep -qE 'firmwareExe|helix' "$f"; then warn "$f" "modifies app_startup.sh but never mentions a UI launcher" @@ -84,7 +83,7 @@ else fi # --- the installer must not hard-fail into a boot loop ---------------------- -for f in payload/run-append.sh payload/report.sh; do +for f in payload/run-append.sh; do [ -f "$f" ] || continue if grep -qE '^[[:space:]]*set -e' "$f"; then bad "$f" "'set -e' in an installer fragment aborts run.sh mid-way, leaving a half-installed system" diff --git a/test/printer/assemble.sh b/test/printer/assemble.sh index 9823364..26c29a9 100644 --- a/test/printer/assemble.sh +++ b/test/printer/assemble.sh @@ -83,9 +83,9 @@ mount -t tmpfs tmpfs $R/run # the suite fail on a small runner. # # Their SIZES are NOT modelled unless you say what they are. The real numbers -# come off the machine in the stage-0 probe report (`df -h`); until -# PROG_MB/DATA_MB are set from it these are unbounded, and an install that -# runs the machine out of space passes here and fails there. +# come off the machine (`df -h` over ssh); until PROG_MB/DATA_MB are set from +# it these are unbounded, and an install that runs the machine out of space +# passes here and fails there. mkdir -p /parts/prog /parts/data if [ -n "${PROG_MB:-}" ]; then mount -t tmpfs tmpfs $R/usr/prog -o size=${PROG_MB}m else mount --bind /parts/prog $R/usr/prog; fi # "usershare" diff --git a/test/printer/seed-prog.sh b/test/printer/seed-prog.sh index 0285da6..2efc979 100644 --- a/test/printer/seed-prog.sh +++ b/test/printer/seed-prog.sh @@ -32,7 +32,7 @@ mkdir -p $R/usr/prog/PROGRAM/software $R/usr/prog/PROGRAM/library \ [ -f $R/usr/prog/.SIMULATED ] || : > $R/usr/prog/.SIMULATED if [ -z "${PROG_MB:-}" ] || [ -z "${DATA_MB:-}" ]; then - echo '/usr/prog and /usr/data sizes (unbounded: set PROG_MB/DATA_MB from the probe report)' \ + echo '/usr/prog and /usr/data sizes (unbounded: set PROG_MB/DATA_MB from df -h on the printer)' \ >> $R/usr/prog/.SIMULATED fi diff --git a/test/run-tests.sh b/test/run-tests.sh index a2dfcc9..c754248 100644 --- a/test/run-tests.sh +++ b/test/run-tests.sh @@ -104,31 +104,18 @@ KLIPPER_FORK="" HELIX_TGZ="$FXASSETS/helixscreen.tar.gz" MAINSAIL_ZIP="$FXASSETS/mainsail.zip" BUSYBOX_BIN="" -DEFAULT_PROFILE=probe TARGET_MACHINE=Creator5Pro ROOT_PW_HASH='\$6\$ci\$abcdefghijklmnopqrstuvwxyz' FF_KEY='FFP0331&*%root' CFG export CONFIG_ENV="$FIXTURE_CFG" -for PROF in probe default; do - hdr "profile: $PROF" - export PROFILE="$PROF" - run ./bin/unpack.sh - run ./bin/patch.sh - run ./bin/pack.sh - PKG=$(ls -1 work/out/Creator5Pro-*.tgz 2>/dev/null | head -n1) - if [ -n "$PKG" ]; then run ./bin/verify.sh "$PKG"; else fail "no package produced for $PROF"; fi -done - -hdr "the probe profile must change nothing" -export PROFILE=probe -./bin/unpack.sh >/dev/null 2>&1 -cp -r work/software "$TMP/sw-before" -./bin/patch.sh >/dev/null 2>&1 -DIFF=$(diff -rq "$TMP/sw-before" work/software 2>&1 | grep -vE 'run\.sh|md5sum\.list' || true) -if [ -z "$DIFF" ]; then pass "probe touches only run.sh (adds the report step)" -else fail "probe modified more than run.sh"; echo "$DIFF" | sed 's/^/ /'; fi +hdr "build on the fixture" +run ./bin/unpack.sh +run ./bin/patch.sh +run ./bin/pack.sh +PKG=$(ls -1 work/out/Creator5Pro-*.tgz 2>/dev/null | head -n1) +if [ -n "$PKG" ]; then run ./bin/verify.sh "$PKG"; else fail "no package produced"; fi hdr "model gates" sub "model gate" ./test/test-model-gate.sh @@ -136,7 +123,7 @@ sub "model gate" ./test/test-model-gate.sh # ============================================================ the replica ==== # Back to the real config for the replica half: it needs the actual stock # package, which no fixture can stand in for. -unset CONFIG_ENV PROFILE TARGET_MACHINE +unset CONFIG_ENV TARGET_MACHINE # Throw away everything the fixture half built. bin/ hardcodes work/, so those # packages land in the same work/out that a real build uses -- and a 380KB @@ -188,22 +175,22 @@ else hdr "chamber heater is gated by model" sub "chamber gate" python3 ./test/test-chamber.py + hdr "our printer.base.cfg is still FlashForge's" + sub "base cfg" python3 ./test/test-base-cfg.py + hdr "MCU bring-up runs on the printer's own Python" sub "mcu bring-up" ./test/sim-mcu-bringup.sh hdr "UI decision and crash protection (on the printer's shell)" sub "ui safety" ./test/sim-ui-fallback.sh - for PROF in probe default; do - hdr "end-to-end update on the printer replica: $PROF" - export PROFILE="$PROF" - run ./bin/unpack.sh - run ./bin/patch.sh - run ./bin/pack.sh - P=$(ls -1 work/out/*-*.tgz 2>/dev/null | head -n1) - if [ -n "$P" ]; then sub "boot -> install -> re-install -> boot ($PROF)" ./test/sim-install.sh "$P" - else fail "no package produced for $PROF"; fi - done + hdr "end-to-end update on the printer replica" + run ./bin/unpack.sh + run ./bin/patch.sh + run ./bin/pack.sh + P=$(ls -1 work/out/*-*.tgz 2>/dev/null | head -n1) + if [ -n "$P" ]; then sub "boot -> install -> re-install -> boot" ./test/sim-install.sh "$P" + else fail "no package produced"; fi hdr "recovery: a stock package reverts the mod" P=$(ls -1 work/out/*-*.tgz 2>/dev/null | head -n1) diff --git a/test/test-ash-conformance.sh b/test/test-ash-conformance.sh index fdd86fa..551ad2f 100644 --- a/test/test-ash-conformance.sh +++ b/test/test-ash-conformance.sh @@ -57,7 +57,7 @@ echo " using: $(echo "$V" | cut -c1-46)" echo for f in /payload/firmwareExe /payload/start.sh /payload/run-pre.sh \ - /payload/run-append.sh /payload/report.sh /payload/init.d/S*; do + /payload/run-append.sh /payload/init.d/S*; do [ -f "$f" ] || continue n=$(basename "$f") if $ASH sh -n "$f" 2>/tmp/err; then