Files
firmware/payload/firmwareExe
T
Oleksandr ShyshatskyiandClaude Opus 5 b5982b09bb Fix eleven defects the first pass introduced
An adversarial re-read of master..HEAD, checking the new text rather than
trusting it. The substantive work held up -- all eight dead-code removals prove
out, SAFE-MODE->MOD_UI is complete, A3's reordering is correct -- but eleven
claims were wrong, and one made a document worse than it found it:

* docs/notes/10-hardware.md said `temperature_sensor motor_value` on
  eboard:PA1 is "not in anything this repo ships". It is:
  printer.motor.cfg:37 declares it and that file is in the package, which is
  also why ff-toolchange.cfg can name MOTOR_STOP. The real nuance is that
  printer.base.cfg does not include printer.motor.cfg. A correct claim in
  25-app-vs-klipper-ownership.md was "corrected" into a false denial.
* docs/toolchange.md pointed at a worked example that reaches 0.125 mm. The
  only example is NOZZLE=220 BED=80, which gives 0.045; the 0.08 bed term
  needs a bed at 100 or above. Both numbers now stated, no forward reference.
* docs/testing.md said 48 tests; pytest collects 53.
* test_config_ownership.py cited bin/patch.sh:80/:88/:128 -- correct on
  master, shifted by two when this branch deleted MARK_BEGIN/MARK_END. The
  line numbers are dropped rather than re-pinned, so they cannot rot again.
* test_includes.py invented a reason for ff-legacy being last ("so its import
  sees every [ff_tool] already declared"). ff_legacy resolves tools at
  klippy:ready; order does not matter.
* fetch-assets.sh's replacement usage text omitted BUILD_MOONRAKER and was
  less accurate than the vague line it replaced.
* 49-runout's sensor table still claimed `extruder: extruderN` after the A1
  fix made that true only of our override, not of the stock file it describes.
* firmwareExe kept "newest version directory" after the same claim was
  corrected in how-it-works.md.
* 25-app inverted the preflight call order and omitted that an M23 print gets
  neither call.
* creator5-safe-moves.gcode called the prepare's G1 Z10 "the one move" below
  Z50; the G28 and offset move before it also go below.
* DOC-DRIFT-AUDIT.md asserted both "Every finding has been applied" and
  "Nothing in this file has been applied", and cited five commits after a
  hash the rebase had rewritten.

53 passed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 19:48:44 +03:00

67 lines
2.8 KiB
Bash
Executable File

#!/bin/sh
# /usr/prog/PROGRAM/software/firmwareExe -- REPLACED by the mod.
#
# The stock boot chain is:
# busybox init -> /etc/init.d/rcS -> S99factory_test_shell
# -> /usr/prog/app_startup.sh -> firmwareExe
# and firmwareExe itself is what launches "/usr/prog/klipper/start.sh &".
#
# Because everything funnels through this one path, replacing this binary
# with a script is the cleanest possible integration point: app_startup.sh,
# rcS and the whole init chain stay 100% STOCK and are never patched.
#
# HelixScreen is the only UI. FlashForge's binary is not kept anywhere: the
# installer wipes the software dir before run.sh anyway, so the way back is
# flashing the stock FlashForge package, which still ships it.
#
# Two further properties we get for free:
# * app_startup.sh's own watchdog greps `ps` for "firmwareExe" 5s after
# launch. This script keeps that name (it IS $0) and stays in the
# FOREGROUND, so the stock watchdog supervises the mod correctly.
# * If this script is ever removed, app_startup.sh restores a firmwareExe
# from a version directory (the last `ls` entry, alphabetical -- and there is
# normally only one) -- the stock recovery path still works.
MODDIR=/usr/data/anvil
[ -f $MODDIR/anvil.conf ] && . $MODDIR/anvil.conf
mkdir -p /usr/data/logs
exec >>/usr/data/logs/anvil-boot.log 2>&1
echo "=== mod firmwareExe `date 2>/dev/null` ==="
# ---- services ------------------------------------------------------------
# init.d-style scripts, run in filename order. One failing service must never
# stop the rest: Klipper has to come up even if the web stack is broken.
if [ -d $MODDIR/init.d ]; then
for s in $MODDIR/init.d/S*; do
[ -x "$s" ] || continue
echo "--- `basename $s` ---"
"$s" start || echo "`basename $s`: returned $?"
done
fi
# ---- the UI, in the foreground so the stock watchdog can see us ----------
# S80ui already decided and wrote its verdict here: "helix" to start the UI,
# "none" to stay headless (MOD_UI=0, or HelixScreen not installed).
UI_CHOICE=`cat $MODDIR/.ui-choice 2>/dev/null || echo none`
echo "ui: choice is $UI_CHOICE"
if [ "$UI_CHOICE" = helix ]; then
HELIX_DATA_DIR=$MODDIR/helixscreen
HELIX_LOG_DEST=file
HELIX_LOG_FILE=/usr/data/logs/helixscreen.log
export HELIX_DATA_DIR HELIX_LOG_DEST HELIX_LOG_FILE
if [ -x $MODDIR/helixscreen/bin/helix-launcher.sh ]; then
$MODDIR/helixscreen/bin/helix-launcher.sh
else
$MODDIR/helixscreen/bin/helix-screen
fi
fi
# If the UI exits -- or was never started at all -- we do NOT exit: dropping
# out of this script makes app_startup.sh think the UI died and re-exec us,
# which would restart every service. Hold the process instead; ssh and
# Mainsail remain available.
echo "ui: nothing left in the foreground -- holding process so services stay up"
while true; do sleep 3600; done