mirror of
https://github.com/Klipper4FlashForge/firmware.git
synced 2026-10-21 21:02:16 -05:00
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.
This commit is contained in:
1 parent
3369a5ee1b
commit
12bbd1e7dc
21 files changed
+143
-370
No files matched your search
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 <target> 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=<p> 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=<p> 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:
|
||||
|
||||
@@ -74,10 +74,10 @@ Not sure which you have? On the printer: **Settings → About**.
|
||||
Afterwards, `http://<printer-ip>/` 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
|
||||
|
||||
+3
-8
@@ -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"
|
||||
|
||||
+22
-14
@@ -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
|
||||
|
||||
+22
-49
@@ -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
|
||||
# <file>.creator5 / <file>.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]
|
||||
|
||||
+4
-4
@@ -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/^/ /'
|
||||
|
||||
+26
-38
@@ -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=<p>` 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
|
||||
<target>` 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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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`.
|
||||
|
||||
|
||||
+4
-5
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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=""
|
||||
+1
-1
@@ -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=""
|
||||
|
||||
+1
-2
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+17
-30
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user