Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
255 changes: 168 additions & 87 deletions .github/workflows/build-sigmastar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,16 @@ on:
description: Publish to this repo's SigmaStar release
type: boolean
default: false
publish:
description: Publish to OpenIPC/firmware latest and report to openipc.org
type: boolean
default: false
# Publishing to OpenIPC/firmware is off for now: see the publish job.
# publish:
# description: Publish to OpenIPC/firmware latest and report to openipc.org
# type: boolean
# default: false

# The shape of build-hisilicon.yml:
# build (matrix, every SoC) -> qemu (prep) -> qemu_smoke (hard gate) ->
# release (own, `release` input) + publish (OpenIPC/firmware latest +
# openipc.org report, `publish` input).
# release (own, `release` input); publish (OpenIPC/firmware latest +
# openipc.org report) is commented out for now.
# build.sh takes SoCs as arguments; the matrix calls it with one SoC per leg.

jobs:
Expand Down Expand Up @@ -60,9 +61,58 @@ jobs:
fail-fast: false
matrix:
include:
- { soc: msc313e, files: "output/u-boot-msc313e-*.bin" }
- { soc: msc316dc, files: "output/u-boot-msc316dc-*.bin" }
- { soc: msc316dm, files: "output/u-boot-msc316dm-*.bin" }
- { soc: msc313e, files: "output/u-boot-msc313e-nor.bin" }
- { soc: msc316dc, files: "output/u-boot-msc316dc-nor.bin" }
- { soc: msc316dm, files: "output/u-boot-msc316dm-nor.bin" }
- { soc: ssc029a-nand, files: "output/u-boot-ssc029a-nand.bin" }
- { soc: ssc029a, files: "output/u-boot-ssc029a-nor.bin" }
- { soc: ssc029b, files: "output/u-boot-ssc029b-nor.bin" }
- { soc: ssc029c, files: "output/u-boot-ssc029c-nor.bin" }
- { soc: ssc375, files: "output/u-boot-ssc375-nor.bin" }
- { soc: ssc034a, files: "output/u-boot-ssc034a-nor.bin" }
- { soc: ssc034b, files: "output/u-boot-ssc034b-nor.bin" }
- { soc: ssc034a-nand, files: "output/u-boot-ssc034a-nand.bin" }
- { soc: ssc034b-nand, files: "output/u-boot-ssc034b-nand.bin" }
- { soc: ssc30kd-nand, files: "output/u-boot-ssc30kd-nand.bin" }
- { soc: ssc30kd, files: "output/u-boot-ssc30kd-nor.bin" }
- { soc: ssc30kq-nand, files: "output/u-boot-ssc30kq-nand.bin" }
- { soc: ssc30kq, files: "output/u-boot-ssc30kq-nor.bin" }
- { soc: ssc325-nand, files: "output/u-boot-ssc325-nand.bin" }
- { soc: ssc325, files: "output/u-boot-ssc325-nor.bin" }
- { soc: ssc325de-nand, files: "output/u-boot-ssc325de-nand.bin" }
- { soc: ssc325de, files: "output/u-boot-ssc325de-nor.bin" }
- { soc: ssc327de-nand, files: "output/u-boot-ssc327de-nand.bin" }
- { soc: ssc327de, files: "output/u-boot-ssc327de-nor.bin" }
- { soc: ssc333-nand, files: "output/u-boot-ssc333-nand.bin" }
- { soc: ssc333, files: "output/u-boot-ssc333-nor.bin" }
- { soc: ssc335-nand, files: "output/u-boot-ssc335-nand.bin" }
- { soc: ssc335, files: "output/u-boot-ssc335-nor.bin" }
- { soc: ssc335de-nand, files: "output/u-boot-ssc335de-nand.bin" }
- { soc: ssc335de, files: "output/u-boot-ssc335de-nor.bin" }
- { soc: ssc337-nand, files: "output/u-boot-ssc337-nand.bin" }
- { soc: ssc337, files: "output/u-boot-ssc337-nor.bin" }
- { soc: ssc337de-nand, files: "output/u-boot-ssc337de-nand.bin" }
- { soc: ssc337de, files: "output/u-boot-ssc337de-nor.bin" }
- { soc: ssc338q-nand, files: "output/u-boot-ssc338q-nand.bin" }
- { soc: ssc338q, files: "output/u-boot-ssc338q-nor.bin" }
- { soc: ssc377-nand, files: "output/u-boot-ssc377-nand.bin" }
- { soc: ssc377, files: "output/u-boot-ssc377-nor.bin" }
- { soc: ssc377d-nand, files: "output/u-boot-ssc377d-nand.bin" }
- { soc: ssc377d, files: "output/u-boot-ssc377d-nor.bin" }
- { soc: ssc377de-nand, files: "output/u-boot-ssc377de-nand.bin" }
- { soc: ssc377de, files: "output/u-boot-ssc377de-nor.bin" }
- { soc: ssc377qe-nand, files: "output/u-boot-ssc377qe-nand.bin" }
- { soc: ssc377qe, files: "output/u-boot-ssc377qe-nor.bin" }
- { soc: ssc378de-nand, files: "output/u-boot-ssc378de-nand.bin" }
- { soc: ssc378de, files: "output/u-boot-ssc378de-nor.bin" }
- { soc: ssc378qe-nand, files: "output/u-boot-ssc378qe-nand.bin" }
- { soc: ssc378qe, files: "output/u-boot-ssc378qe-nor.bin" }
- { soc: ssd201-nand, files: "output/u-boot-ssd201-nand.bin" }
- { soc: ssd201, files: "output/u-boot-ssd201-nor.bin" }
- { soc: ssd202d-nand, files: "output/u-boot-ssd202d-nand.bin" }
- { soc: ssd202d, files: "output/u-boot-ssd202d-nor.bin" }
- { soc: ssr621q-nand, files: "output/u-boot-ssr621q-nand.bin" }
- { soc: ssr621q, files: "output/u-boot-ssr621q-nor.bin" }

steps:
- name: Checkout
Expand Down Expand Up @@ -124,7 +174,22 @@ jobs:
done
[ "$found" = 1 ] || { echo "missing ${kind} image for ${soc} (${pattern})" >&2; rc=1; }
}
check_kind nor 256 "output/*${soc}*-nor.bin"
# SPI NAND: the boot area ends where the die's environment
# starts (include/configs/openipc-common.h on openipc-sigmastar):
# 0x200000, infinity2m 0x440000, infinity6c 0x4C0000, Ifliegen
# 0x500000, Iford 0x580000.
case "${soc}" in
ssd201-nand|ssd202d-nand|ssr621q-nand)
check_kind nand 4352 "output/u-boot-${soc}.bin" ;;
ssc377*-nand|ssc378*-nand)
check_kind nand 4864 "output/u-boot-${soc}.bin" ;;
ssc034a-nand|ssc034b-nand)
check_kind nand 5120 "output/u-boot-${soc}.bin" ;;
ssc029a-nand)
check_kind nand 5632 "output/u-boot-${soc}.bin" ;;
*-nand) check_kind nand 2048 "output/u-boot-${soc}.bin" ;;
*) check_kind nor 256 "output/u-boot-${soc}-nor.bin" ;;
esac
exit $rc

- name: Upload artifact
Expand Down Expand Up @@ -168,7 +233,9 @@ jobs:
# then bring up DDR and unpack U-Boot. It asserts U-Boot reaches the
# autoboot prompt. There is no MSC316 machine: the MSC316 images boot on
# msc313e too (their IPL sizes its 64 MiB), which checks all but their
# DDR set-up, so every SoC is a hard gate on release.
# DDR set-up, so every SoC is a hard gate on release. The infinity2m
# images boot on their own machines the same way. The infinity6 dies have
# no machine, so they are built but not booted here.
#
# The second boot must load the environment the first saved, which
# proves the driver's writes land where its reads find them.
Expand All @@ -179,7 +246,7 @@ jobs:
strategy:
fail-fast: false
matrix:
soc: [msc313e, msc316dc, msc316dm]
soc: [msc313e, msc316dc, msc316dm, ssd201, ssd202d]
steps:
- name: Download qemu-arm
uses: actions/download-artifact@v4
Expand Down Expand Up @@ -211,16 +278,20 @@ jobs:
UBOOT="u-boot-${soc}-nor.bin"
test -f "$UBOOT"
echo "booting $UBOOT"
# 8 MiB NOR, U-Boot at 0, the rest erased
python3 - "$UBOOT" /tmp/flash.bin <<'PY'
# One machine for the whole infinity3 family, each its own for
# infinity2m; 8 or 16 MiB NOR, U-Boot at 0, the rest erased
case "$soc" in
msc*) MACHINE=msc313e; MIB=8 ;;
*) MACHINE=$soc; MIB=16 ;;
esac
python3 - "$UBOOT" /tmp/flash.bin "$MIB" <<'PY'
import sys
img = bytearray(b'\xff' * (8 << 20))
img = bytearray(b'\xff' * (int(sys.argv[3]) << 20))
u = open(sys.argv[1], 'rb').read()
img[:len(u)] = u
open(sys.argv[2], 'wb').write(img)
PY
# One machine for the whole infinity3 family
FLASH="-M msc313e,flash-file=/tmp/flash.bin"
FLASH="-M $MACHINE,flash-file=/tmp/flash.bin"
chmod +x ./qemu-arm
# Two boots: the first finds an erased environment and saves the
# default one; the second must load it back.
Expand Down Expand Up @@ -283,76 +354,86 @@ jobs:
files: artifacts/**/*.bin
fail_on_unmatched_files: true

# Publish every image to the OpenIPC/firmware `latest` release and tell
# openipc.org what was uploaded. openipc.org keeps, per file name, the
# newest uboot build that names it, so this run adds or refreshes the
# u-boot-msc31* names and leaves the other repositories' files alone. The
# concurrency group, shared with build-hisilicon.yml, keeps a second run
# from uploading between this run's upload and its report.
publish:
needs: [resolve, build, qemu_smoke]
if: ${{ github.event_name == 'workflow_dispatch' && inputs.publish }}
runs-on: ubuntu-latest
timeout-minutes: 30
concurrency:
group: publish-firmware-latest
cancel-in-progress: false
permissions:
contents: read
id-token: write
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
pattern: u-boot-*
# Off for now: images go only to this repository's own SigmaStar release.
# Uncomment the job and the `publish` input to publish again.
# # Publish the infinity3 images to the OpenIPC/firmware `latest` release and
# # tell openipc.org what was uploaded. openipc.org keeps, per file name, the
# # newest uboot build that names it, so this run adds or refreshes the
# # u-boot-msc31* names and leaves the other repositories' files alone.
# #
# # Only those names: u-boot-ssc* in `latest` are the vendor U-Boot that
# # OpenIPC/u-boot-sigmastar publishes and cameras in the field flash, and the
# # infinity6 images built here have not run on silicon (no qemu machine
# # either). Widen PUBLISH_GLOB one die at a time, after testing on a board.
# # The
# # concurrency group, shared with build-hisilicon.yml, keeps a second run
# # from uploading between this run's upload and its report.
# publish:
# needs: [resolve, build, qemu_smoke]
# if: ${{ github.event_name == 'workflow_dispatch' && inputs.publish }}
# runs-on: ubuntu-latest
# timeout-minutes: 30
# concurrency:
# group: publish-firmware-latest
# cancel-in-progress: false
# permissions:
# contents: read
# id-token: write
# env:
# PUBLISH_GLOB: u-boot-msc31*.bin
# steps:
# - name: Download artifacts
# uses: actions/download-artifact@v4
# with:
# path: artifacts
# pattern: u-boot-*

- name: Upload to OpenIPC/firmware latest release
env:
GH_TOKEN: ${{ secrets.FIRMWARE_RELEASE_TOKEN }}
run: |
set -eu
# Releases API occasionally returns 502/503. Retry with backoff:
# 10s, 20s, 30s, 40s -- total ~100s before giving up.
upload() {
local f="$1" i
for i in 1 2 3 4 5; do
if gh release upload latest "$f" --clobber -R OpenIPC/firmware; then
return 0
fi
[ "$i" = "5" ] && return 1
echo "upload attempt $i failed; sleeping $((i*10))s" >&2
sleep $((i*10))
done
}
find artifacts -type f -name '*.bin' | sort | while read -r f; do
echo "publishing $f"
upload "$f"
done
# - name: Upload to OpenIPC/firmware latest release
# env:
# GH_TOKEN: ${{ secrets.FIRMWARE_RELEASE_TOKEN }}
# run: |
# set -eu
# # Releases API occasionally returns 502/503. Retry with backoff:
# # 10s, 20s, 30s, 40s -- total ~100s before giving up.
# upload() {
# local f="$1" i
# for i in 1 2 3 4 5; do
# if gh release upload latest "$f" --clobber -R OpenIPC/firmware; then
# return 0
# fi
# [ "$i" = "5" ] && return 1
# echo "upload attempt $i failed; sleeping $((i*10))s" >&2
# sleep $((i*10))
# done
# }
# find artifacts -type f -name "$PUBLISH_GLOB" | sort | while read -r f; do
# echo "publishing $f"
# upload "$f"
# done

# The push script is OpenIPC/firmware's, at a fixed commit: the only
# code this job checks out, since it holds an id-token.
- uses: actions/checkout@v4
with:
repository: OpenIPC/firmware
ref: 7fa63ce694cb5d27c19d4f19058ba2c044849db4
sparse-checkout: .github/scripts
path: firmware
# # The push script is OpenIPC/firmware's, at a fixed commit: the only
# # code this job checks out, since it holds an id-token.
# - uses: actions/checkout@v4
# with:
# repository: OpenIPC/firmware
# ref: 7fa63ce694cb5d27c19d4f19058ba2c044849db4
# sparse-checkout: .github/scripts
# path: firmware

# The contract is PUSH.md in OpenIPC/website (source `uboot`, release
# `latest`, one id per run). The digests are of the files uploaded
# above, hashed here, so the push describes exactly those bytes.
- name: Report to openipc.org
env:
SS_SHA: ${{ needs.resolve.outputs.sha }}
run: |
set -eu
mkdir published
find artifacts -type f -name '*.bin' -exec cp {} published/ \;
python3 firmware/.github/scripts/push_build.py \
--source uboot \
--build-id "uboot-sigmastar-$(date -u +%Y%m%dT%H%M%SZ)-${SS_SHA::7}" \
--release latest \
--sha "$SS_SHA" \
--built-at "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
--assets 'published/*.bin'
# # The contract is PUSH.md in OpenIPC/website (source `uboot`, release
# # `latest`, one id per run). The digests are of the files uploaded
# # above, hashed here, so the push describes exactly those bytes.
# - name: Report to openipc.org
# env:
# SS_SHA: ${{ needs.resolve.outputs.sha }}
# run: |
# set -eu
# mkdir published
# find artifacts -type f -name "$PUBLISH_GLOB" -exec cp {} published/ \;
# python3 firmware/.github/scripts/push_build.py \
# --source uboot \
# --build-id "uboot-sigmastar-$(date -u +%Y%m%dT%H%M%SZ)-${SS_SHA::7}" \
# --release latest \
# --sha "$SS_SHA" \
# --built-at "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
# --assets 'published/*.bin'
41 changes: 27 additions & 14 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ own branch:
plus the SDK's nsboot, built from source in the tree. CI:
`build-grainmedia.yml`, called from that branch's `ci.yml`. Its own
`CLAUDE.md` covers nsboot, the image layout and the kernel hand-off.
- `openipc-sigmastar`: U-Boot for SigmaStar MSC313E, MSC316DC and
MSC316DM (infinity3), on the same mainline release with the same
- `openipc-sigmastar`: U-Boot for SigmaStar infinity3 (MSC313E, MSC316DC,
MSC316DM), infinity2m (SSD201, SSD202D, SSR621Q), infinity6, 6b0, 6e, 6c
(SSC3xx), Iford (SSC029A/B/C), Ifado (SSC375) and Ifliegen (SSC034A/B),
NOR and SPI NAND, on the same mainline release with the same
OpenIPC layer, behind the vendor's IPL and IPL_CUST, carried as
binaries. CI: `build-sigmastar.yml`, called from that branch's
`ci.yml`. Its own `CLAUDE.md` covers the boot chain, the image layout
Expand Down Expand Up @@ -264,21 +266,32 @@ The build logic lives here. Other branches call it:
## `build-sigmastar.yml`

- It is `build-anyka.yml` for `openipc-sigmastar`: the same job graph and
`resolve`/`ref` rules, NOR only (256 KiB boot partition: MXP table,
the vendor IPL and IPL_CUST, U-Boot in the 128 KiB MXP partition
`UBOOT`).
- **Images are not machines:** qemu-hisilicon has an `msc313e` machine
only (#213 or later). Every leg, the MSC316 ones too, boots on
`-M msc313e`; the MSC316 IPL sizes its 64 MiB. Keep the build matrix,
the smoke matrix and the README's list in step.
- **Smoke test:** two boots of an 8 MiB flash image holding only the
image; the machine's mask ROM loads the IPL from 0x4000. It passes on
`resolve`/`ref` rules, NOR and SPI NAND. A NOR image is the 256 KiB
boot partition (the vendor's IPL, IPL_CUST and on Ifliegen TF-A, the
die's flash table, U-Boot). A SPI NAND one is the boot area up to the
die's environment, as the fit check limits it: 2 MiB, 4352 KiB on
infinity2m, 4864 KiB on infinity6c, 5120 KiB on Ifliegen, 5632 KiB on
Iford.
- **Images are not machines:** the infinity3 legs, the MSC316 ones too,
boot on `-M msc313e` (#213 or later); the MSC316 IPL sizes its 64 MiB.
`ssd201` and `ssd202d` boot on their own machines. The other legs are
built and fit-checked, not booted here (their qemu machines are not in
the qemu-hisilicon CI uses). Keep the build
matrix, the smoke matrix and the README's list in step.
- **Smoke test:** two boots of an 8 MiB (infinity3) or 16 MiB (infinity2m)
flash image holding only the image; the machine's mask ROM loads the IPL.
It passes on
`Hit Ctrl-C`, and fails if the second boot reports a bad environment CRC.
- **Release and publish:**
- `release` uploads to the `sigmastar` tag.
- `publish` shares the `publish-firmware-latest` concurrency group and
reports a `uboot-sigmastar-…` build id. No other repository
publishes `u-boot-msc31*` names to `latest`.
- `publish` is commented out for now, with its input: SigmaStar images
go only to the `sigmastar` release. When it returns, it shares the
`publish-firmware-latest` concurrency group and reports a
`uboot-sigmastar-…` build id. No other repository
publishes `u-boot-msc31*` names to `latest`, and `PUBLISH_GLOB` keeps
`publish` to those: `u-boot-ssc*` in `latest` are
OpenIPC/u-boot-sigmastar's vendor U-Boot, which cameras flash, and the
ones built here have not run on silicon. `release` carries them all.
- openipc.org accepts the report only from workflows it allowlists
(OpenIPC/website `service/internal/builds/verify.go`).
`build-sigmastar.yml` has to be added there before the first
Expand Down
Loading
Loading