mirror of
https://github.com/openglow-org/forgefirm.git
synced 2026-09-28 01:01:12 -07:00
image: slot-sized release rootfs, ext4 artifact, fwup, mkfw.sh
The release image now targets the 200 MiB factory eMMC slot: content plus 40 MiB working space, hard build failure past the slot size. The raw ext4 is deployed alongside the wic; scripts/mkfw.sh packs it into a signed .fw with factory-pattern upgrade.a/upgrade.b tasks. fwup 1.16.0 recipe (applies ForgeFIRM and Glowforge-signed archives on device) is installed in both images. Dev images stay SD-sized with a 256 MiB working margin and no ceiling. Verified on the 20260808153331 build: release ext4 180.8 MiB; signed .fw applies byte-exact with fwup 1.16.0 and with the factory's 0.14.2 (raw-format pubkey), and 0.14.2 -V verifies the signature.
This commit is contained in:
@@ -113,6 +113,15 @@ motion constants were extracted from the `_RESOURCES` pulse files
|
|||||||
kas/forgefirm-glowforge.yml -c 'bitbake forgefirm-image
|
kas/forgefirm-glowforge.yml -c 'bitbake forgefirm-image
|
||||||
forgefirm-image-dev'`. Artifacts:
|
forgefirm-image-dev'`. Artifacts:
|
||||||
`forgefirm/build/tmp/deploy/images/glowforge/`.
|
`forgefirm/build/tmp/deploy/images/glowforge/`.
|
||||||
|
- **fwup lab (host)**: `~/fwup-lab/bin/` holds host-built `fwup-0.14.2`
|
||||||
|
(factory-era) and `fwup-v1.16.0`; `~/fwup-lab/devkeys/fwup-key.{priv,pub}`
|
||||||
|
is the DEV signing keypair (`fwup-key-raw.pub` = raw 32-byte form —
|
||||||
|
what fwup 0.14.2 expects; 1.x reads both). Cross-version compat is
|
||||||
|
proven both ways (modern-packed signed archives apply with 0.14.2;
|
||||||
|
modern fwup verifies+applies the factory .fw — signer key
|
||||||
|
2017-05-001.pub). The production release key does not exist yet —
|
||||||
|
generation/custody is an operator ceremony (UPDATE-SYSTEM.md gate 3).
|
||||||
|
Pack releases with `scripts/mkfw.sh`.
|
||||||
- **Shell gotchas** (cost real time): PowerShell mangles embedded double
|
- **Shell gotchas** (cost real time): PowerShell mangles embedded double
|
||||||
quotes in git-commit here-strings (avoid `"` in messages); `wsl -- bash
|
quotes in git-commit here-strings (avoid `"` in messages); `wsl -- bash
|
||||||
-c '...'` eats `$VAR` expansions (use script files run via PowerShell,
|
-c '...'` eats `$VAR` expansions (use script files run via PowerShell,
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
SUMMARY = "Configurable embedded Linux firmware update creator and runner"
|
||||||
|
DESCRIPTION = "Applies and creates signed .fw firmware archives. ForgeFIRM \
|
||||||
|
uses the factory's own update format: fwup applies ForgeFIRM upgrades and \
|
||||||
|
Glowforge factory-restore archives to the inactive rootfs slot."
|
||||||
|
HOMEPAGE = "https://github.com/fwup-home/fwup"
|
||||||
|
LICENSE = "Apache-2.0"
|
||||||
|
LIC_FILES_CHKSUM = "file://LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57"
|
||||||
|
|
||||||
|
DEPENDS = "libconfuse libarchive libsodium"
|
||||||
|
|
||||||
|
SRC_URI = "https://github.com/fwup-home/fwup/releases/download/v${PV}/fwup-${PV}.tar.gz"
|
||||||
|
SRC_URI[sha256sum] = "a07b79268247ecee134a916ab928914be2a4ecbac0bc5e5f19212ec36ecb5c21"
|
||||||
|
|
||||||
|
inherit autotools pkgconfig bash-completion
|
||||||
@@ -12,6 +12,11 @@ IMAGE_FEATURES += " \
|
|||||||
tools-debug \
|
tools-debug \
|
||||||
"
|
"
|
||||||
|
|
||||||
|
# Dev images boot from SD, never from a 200 MiB eMMC slot: lift the slot
|
||||||
|
# ceiling and give the filesystem generous working space instead.
|
||||||
|
IMAGE_ROOTFS_MAXSIZE = ""
|
||||||
|
IMAGE_ROOTFS_EXTRA_SPACE = "262144"
|
||||||
|
|
||||||
# Dev builds identify by build timestamp (matches the artifact name),
|
# Dev builds identify by build timestamp (matches the artifact name),
|
||||||
# tagged so a bench machine is never mistaken for a release.
|
# tagged so a bench machine is never mistaken for a release.
|
||||||
FORGEFIRM_VERSION_STRING = "${DATETIME} (dev)"
|
FORGEFIRM_VERSION_STRING = "${DATETIME} (dev)"
|
||||||
|
|||||||
@@ -16,7 +16,19 @@ IMAGE_INSTALL:remove = "gfui-client"
|
|||||||
# for $H when homing_mode = gfcloud (/data/forgefirm.conf).
|
# for $H when homing_mode = gfcloud (/data/forgefirm.conf).
|
||||||
# v4l-utils provides media-ctl / v4l2-ctl for the imx-media pipeline (also a
|
# v4l-utils provides media-ctl / v4l2-ctl for the imx-media pipeline (also a
|
||||||
# forgectrl runtime dependency, kept explicit here for bring-up use).
|
# forgectrl runtime dependency, kept explicit here for bring-up use).
|
||||||
IMAGE_INSTALL:append = " grblhal-glowforge forgectrl gfhome v4l-utils"
|
# fwup: applies signed .fw archives (ForgeFIRM upgrades + factory restore)
|
||||||
|
# to the inactive rootfs slot.
|
||||||
|
IMAGE_INSTALL:append = " grblhal-glowforge forgectrl gfhome v4l-utils fwup"
|
||||||
|
|
||||||
|
# The release rootfs must fit a 200 MiB factory eMMC slot (409600 blocks).
|
||||||
|
# Sizing: content + 40 MiB working space, hard-capped at the slot size —
|
||||||
|
# the build fails rather than emit an unflashable image. The raw ext4 is
|
||||||
|
# deployed alongside the wic; scripts/mkfw.sh packs it into the signed
|
||||||
|
# .fw release artifact.
|
||||||
|
IMAGE_FSTYPES:append = " ext4"
|
||||||
|
IMAGE_OVERHEAD_FACTOR = "1.0"
|
||||||
|
IMAGE_ROOTFS_EXTRA_SPACE = "40960"
|
||||||
|
IMAGE_ROOTFS_MAXSIZE = "204800"
|
||||||
|
|
||||||
# Version stamp: /etc/forgefirm-version (machine-readable), echoed on the
|
# Version stamp: /etc/forgefirm-version (machine-readable), echoed on the
|
||||||
# serial-console login prompt (/etc/issue) and at SSH login (motd).
|
# serial-console login prompt (/etc/issue) and at SSH login (motd).
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
#!/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"
|
||||||
|
PUB="${KEY%.priv}.pub"
|
||||||
|
if [ -f "$PUB" ]; then
|
||||||
|
"$FWUP" -V -i "$OUT" -p "$PUB" || { echo "ERROR: signature self-check failed" >&2; exit 1; }
|
||||||
|
fi
|
||||||
|
echo "signed: $OUT"
|
||||||
|
else
|
||||||
|
cp "$WORK/unsigned.fw" "$OUT"
|
||||||
|
echo "UNSIGNED (dev only): $OUT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
"$FWUP" -m -i "$OUT" | head -4
|
||||||
Reference in New Issue
Block a user