mirror of
https://github.com/openglow-org/forgefirm.git
synced 2026-09-27 16:51:12 -07:00
- Controllers stop at K80, before forgectrl at K90: runlevel 0/6 no longer tears down the cooling engine, fire gates, and broker while a controller may still be executing a job. - The grblhal/gfcloud init scripts are real emergency levers: stop routes through the supervisor (POST /controller/stop - a bare pkill was safed and respawned seconds later), start resumes supervision, status exists, and the pkill fallback matches full executable paths instead of truncated names or bare substrings. - slotmigrate: the partition grow gets the same 2048-sector tolerance as the filesystem branch (an exact compare rewrote the MBR at S02 on every boot on disks where the grow cannot land on the last sector), verifies it made progress, and the resize2fs retry is bounded at three attempts with the counter kept on p3 itself. - Installer: archive product/platform are verified after the signature, and a validly signed OLDER release now requires an explicit yes instead of installing as a silent downgrade. All predictable /tmp paths in the installer and ffboot are mktemp now. - release.sh rejects multiple positional versions (the last one used to win silently) and a release without factory-era verification dies unless explicitly bypassed; mkfw.sh refuses to pack when the public key for the post-sign self-check is missing. - forgefirm-logrotate: size-capped rotation (boot + hourly) for the /data logs - a full /data breaks settings, update staging, and the controllers own writes. - Bench build scripts derive every path from their own location or FF_SRC_TOP/FF_BUILD_TOP and log to mktemp files.
87 lines
2.7 KiB
Bash
87 lines
2.7 KiB
Bash
#!/bin/sh
|
|
# (C) Copyright 2020-2026
|
|
# Scott Wiederhold, s.e.wiederhold@gmail.com
|
|
# https://community.openglow.org
|
|
# SPDX-License-Identifier: MIT
|
|
#
|
|
# Packs a ForgeFIRM rootfs.ext4 into a fwup .fw archive with the factory
|
|
# update task layout: upgrade.a / upgrade.b raw-write the rootfs into eMMC
|
|
# slot p1 / p2 (fwup is invoked with -d /dev/mmcblk2p<N>, so offsets are
|
|
# partition-relative, exactly like the factory updater).
|
|
#
|
|
# Usage: mkfw.sh <rootfs.ext4> <version> <output.fw> [private-key]
|
|
# FWUP=<path> overrides the fwup binary (any 1.x; archives verified to
|
|
# apply with the factory's fwup 0.14.2).
|
|
# Unsigned output (no key) is for dev only: release and updater paths
|
|
# require a signature.
|
|
|
|
set -e
|
|
|
|
FWUP="${FWUP:-fwup}"
|
|
ROOTFS="$1"
|
|
VERSION="$2"
|
|
OUT="$3"
|
|
KEY="$4"
|
|
|
|
usage () {
|
|
echo "usage: mkfw.sh <rootfs.ext4> <version> <output.fw> [private-key]" >&2
|
|
exit 2
|
|
}
|
|
|
|
[ -n "$ROOTFS" ] && [ -n "$VERSION" ] && [ -n "$OUT" ] || usage
|
|
[ -f "$ROOTFS" ] || { echo "ERROR: rootfs '$ROOTFS' not found" >&2; exit 1; }
|
|
command -v "$FWUP" >/dev/null || { echo "ERROR: fwup not found (set FWUP=)" >&2; exit 1; }
|
|
|
|
# The rootfs must fit the 200 MiB factory slot (409600 x 512-byte blocks).
|
|
SLOT_BYTES=209715200
|
|
SIZE=$(wc -c < "$ROOTFS")
|
|
[ "$SIZE" -le "$SLOT_BYTES" ] || {
|
|
echo "ERROR: rootfs is $SIZE bytes; slot holds $SLOT_BYTES" >&2; exit 1; }
|
|
|
|
WORK=$(mktemp -d)
|
|
trap 'rm -rf "$WORK"' EXIT
|
|
cp "$ROOTFS" "$WORK/rootfs.ext4"
|
|
|
|
cat > "$WORK/fwup.conf" <<EOF
|
|
meta-product = "ForgeFIRM firmware"
|
|
meta-description = "ForgeFIRM firmware for Glowforge brand CNC lasers"
|
|
meta-version = "${VERSION}"
|
|
meta-platform = "glowforge"
|
|
meta-architecture = "arm"
|
|
meta-author = "OpenGlow"
|
|
|
|
file-resource rootfs.ext4 {
|
|
host-path = "${WORK}/rootfs.ext4"
|
|
}
|
|
|
|
task upgrade.a {
|
|
require-unmounted-destination = true
|
|
verify-on-the-fly = true
|
|
on-resource rootfs.ext4 { raw_write(0) }
|
|
}
|
|
|
|
task upgrade.b {
|
|
require-unmounted-destination = true
|
|
verify-on-the-fly = true
|
|
on-resource rootfs.ext4 { raw_write(0) }
|
|
}
|
|
EOF
|
|
|
|
"$FWUP" -c -f "$WORK/fwup.conf" -o "$WORK/unsigned.fw"
|
|
|
|
if [ -n "$KEY" ]; then
|
|
[ -f "$KEY" ] || { echo "ERROR: key '$KEY' not found" >&2; exit 1; }
|
|
"$FWUP" -S -s "$KEY" -i "$WORK/unsigned.fw" -o "$OUT"
|
|
# The post-sign self-check is mandatory: packing without it means a
|
|
# release could ship with a signature nothing ever verified.
|
|
PUB="${KEY%.priv}.pub"
|
|
[ -f "$PUB" ] || { echo "ERROR: public key '$PUB' not found - cannot self-check the signature; refusing to pack unverified" >&2; exit 1; }
|
|
"$FWUP" -V -i "$OUT" -p "$PUB" || { echo "ERROR: signature self-check failed" >&2; exit 1; }
|
|
echo "signed: $OUT"
|
|
else
|
|
cp "$WORK/unsigned.fw" "$OUT"
|
|
echo "UNSIGNED (dev only): $OUT"
|
|
fi
|
|
|
|
"$FWUP" -m -i "$OUT" | head -4
|