Skip to content

sysupgrade: route by build platform + SoC aliases; cv6xx combined-image OTA#2181

Merged
widgetii merged 3 commits into
masterfrom
feat/sysupgrade-build-platform-soc-alias
Jun 7, 2026
Merged

sysupgrade: route by build platform + SoC aliases; cv6xx combined-image OTA#2181
widgetii merged 3 commits into
masterfrom
feat/sysupgrade-build-platform-soc-alias

Conversation

@widgetii

@widgetii widgetii commented Jun 6, 2026

Copy link
Copy Markdown
Member

Problem

sysupgrade derives a camera's upgrade identity from the chip (fw_printenv -n soc, effectively ipcinfo chip detection) and requires it to exactly equal the published SOC_MODEL. That breaks two ways:

  • hi3516cv6xx: add OS02M10 + IMX307 sensor drivers #2175 regression — the single hi3516cv6xx image serves dies that report hi3516cv610 / hi3516cv608, so the chip's id never matches the published hi3516cv6xx at any of the upgrade steps (extracted filenames, kernel/rootfs SoC checks, default download name, manifest key) → "Wrong SoC" / "No artifact" / file-not-found.
  • Wasted CI — we build byte-identical pairs that differ only in SOC_MODEL (xm530/xm550, gk7205v200/gk7205v210) purely so each chip can find "its" image.

Key invariant: no SOC_MODEL contains _, so SOC_MODEL is the leading _-token of BUILD_PLATFORM (holds even for builder's ${soc}_${variant}_${device}).

Changes

1. Identity by build platform, not chip (general/overlay/usr/sbin/sysupgrade, 1.0.52 → 1.0.53)
Derive model from os-release BUILD_PLATFORM; fall back to fw_printenv only when absent and make it non-fatal (it also fails under QEMU). All upgrade-identity uses switch from $soc to $model; check_soc validates the image's stamped SoC against $model. This alone fixes cv6xx with no data files.

2. SoC-alias indirection (one image legitimately serves several chips)
New BR2_OPENIPC_SOC_ALIASES defconfig field (general/Config.in + external.mk), declared on hi3516cv6xx_ultimate (hi3516cv610 hi3516cv608), xm530_lite (xm550), gk7205v200_lite (gk7205v210). enrich_manifest.py scans the defconfigs and emits @alias <chip> <model> into manifest.flat + an aliases map in manifest.json (schema unchanged; rows are inert to the existing busybox awk readers). resolve_model_alias() rewrites model via the manifest, with a small static net so offline / --archive migrations also resolve.

3. CI dedup (.github/workflows/build.yml)
Drop the duplicate gk7205v210_lite and xm550_lite matrix entries. Their defconfigs are kept (excluded from CI, still buildable locally; documented with a NOTE header).

4. cv6xx combined-image upgrade variant
cv6xx ships one firmware.bin = FIT kernel + rootfs in a single blob with a floating boundary. New do_update_firmware(): flash the whole blob to a dedicated firmware partition when one exists (flexible kernel/rootfs split), else slice it at the FIT boundary onto the existing kernel/rootfs partitions. FIT-aware guards in do_update_kernel and get_kernel_version (the uImage offset probes misfire on a FIT).

Verification

  • Host unit tests — model/platform derivation, FIT 64K-block math (= the real 2816 KiB rootfs offset), @alias awk inertness, scan_aliases{xm550:xm530, gk7205v210:gk7205v200, hi3516cv610:hi3516cv6xx, hi3516cv608:hi3516cv6xx}.
  • Host integration — the real script vs the real cv6xx .tgz, mocking only camera-only binaries: 16/16 (real FIT split, real squashfs hostname check, flashcp → /dev/mtd2//dev/mtd3; plus xm550→xm530 --list-builds).
  • Real QEMU boot (~/git/qemu-hisilicon, -M hi3516cv610, on-image busybox, expect-driven): 11/11Model=hi3516cv6xx resolves from BUILD_PLATFORM despite fw_printenv failing, and combined --build runs download → split → FIT guard → loop-mount + SoC OK, up to the flash step.

The flashcp write itself can't be exercised in QEMU (the hi3516cv610 machine has no SPI-NOR) — that still needs a real CV610 board.

Follow-up (not in this PR)

The fully-flexible whole-blob path needs a combined firmware mtdparts partition + a u-boot bootcmd that locates rootfs at the dynamic post-FIT offset (u-boot/board repo). Until then the split-fallback path works on the current cv6xx layout. Stale openipc.xm550-*.tgz / openipc.gk7205v210-*.tgz assets on the rolling releases can be deleted once to fully retire those keys.

🤖 Generated with Claude Code

…bined image

Self-upgrade derived the camera's identity from the chip (fw_printenv -n soc /
ipcinfo) and required it to exactly equal the published SOC_MODEL, so one image
named hi3516cv6xx could not be found or validated by a die reporting
hi3516cv610/hi3516cv608 (regression from #2175), and it forced wasted CI builds
of byte-identical pairs (xm530/xm550, gk7205v200/gk7205v210).

- sysupgrade (1.0.52 -> 1.0.53): derive `model` from os-release BUILD_PLATFORM
  (leading _-token; no SOC_MODEL contains '_'), fall back to fw_printenv only
  when absent and make it non-fatal. Use `model` for the manifest key, default
  download name, extracted artifact names and check_soc. Add
  resolve_model_alias() (manifest @alias records + a small static net). Add
  do_update_firmware() for the cv6xx combined image (FIT kernel + rootfs in one
  blob): whole-blob flash to a `firmware` partition when present, else split at
  the FIT boundary onto the existing kernel/rootfs partitions. FIT-aware guards
  in do_update_kernel and get_kernel_version.
- New BR2_OPENIPC_SOC_ALIASES defconfig field (Config.in + external.mk export);
  declared on hi3516cv6xx_ultimate (hi3516cv610/608), xm530_lite (xm550),
  gk7205v200_lite (gk7205v210).
- enrich_manifest.py: scan defconfigs and emit @alias records into
  manifest.flat plus an aliases map in manifest.json (schema unchanged; the
  rows are inert to the existing busybox awk readers).
- build.yml: drop the duplicate gk7205v210_lite and xm550_lite matrix entries.
  Their defconfigs are kept (excluded from CI, still buildable locally).

Verified with host unit tests, a host integration harness against the real
cv6xx tgz (16/16), and a real QEMU boot under the on-image busybox (11/11) up to
the flash step (the hi3516cv610 QEMU machine has no SPI-NOR to flashcp).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Validated the combined-image OTA against a full 16 MB SPI-NOR image in the
hi3516cv610 QEMU machine (HiFMC emulation, flash-boot from NOR, real /proc/mtd
partitions). The full-flash test surfaced two issues:

- do_update_firmware preferred the dedicated "firmware" partition, but on cv6xx
  that partition OVERLAPS kernel+rootfs (env: 7168k@0x50000). Writing it via
  flashcp is risky and, for a fixed-offset U-Boot, only boot-consistent when the
  kernel partition happens to equal the FIT size. Prefer the traditional
  non-overlapping split instead: slice the blob at the FIT boundary and flash
  the FIT to the kernel partition and the rootfs to the rootfs partition (U-Boot
  reads each from its fixed offset). Whole-blob flash to a dedicated "firmware"
  partition is now only the fallback for a pure-combined layout (no separate
  kernel/rootfs partitions).
- the whole-blob branch ignored flashcp's exit status and always printed
  "Firmware updated"; it now `|| die`s on flashcp failure.

The QEMU HiFMC model verified the kernel/FIT write to NOR end-to-end; it
intentionally write-protects detected SquashFS blocks, so an in-emulator rootfs
flashcp is blocked by design (real hardware flashes the rootfs normally). Host
sysupgrade harness still 16/16.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@widgetii

widgetii commented Jun 7, 2026

Copy link
Copy Markdown
Member Author

Validated sysupgrade 1.0.53 under QEMU — hi3516ev300 + hi3516cv610, both pass

Tested this branch's general/overlay/usr/sbin/sysupgrade (1.0.53) end-to-end in QEMU (the qemu-hisilicon machine models). Flash writes go through an emulated HiFMC V100 NOR with a recent erase/program fix, so flash_eraseall / flashcp -v behave like hardware — every verify below actually passed.

hi3516ev300 — split layout, uImage kernel

Booted the unmodified hi3516ev300_lite 8 MiB NOR; ran the 1.0.53 script directly.

  • Identity: SoC hi3516ev300 / Model hi3516ev300 (from BUILD_PLATFORM=hi3516ev300_lite)
  • sysupgrade -k -r -f -x -z (online, real GitHub firmware): kernel → mtd2(kernel) (32 blk) + rootfs → mtd3(rootfs) (75 blk), both flashcp -v verified → Kernel updated / RootFS updated, version bumped
  • firstboot: do_wipe_overlay erased mtd4(rootfs_data)

hi3516cv610 — combined image, FIT kernel (the cv6xx case this PR targets)

Used the official firmware.bin.hi3516cv6xx (BUILD_PLATFORM=hi3516cv6xx_ultimatemodel=hi3516cv6xx): a cv610 die running the shared cv6xx image. Booted the FIT-extracted kernel/dtb/rootfs with a 16 MiB NOR providing the boot/env/kernel/rootfs/rootfs_data partitions.

  • Identity decoupled from the chip: Model hi3516cv6xx, and SoC printed blank with no abort (this guest had no populated U-Boot env, so fw_printenv -n soc returned nothing). 1.0.52 would die "SoC is not defined"; the non-fatal fallback + BUILD_PLATFORM identity is exactly what lets 1.0.53 proceed. ✅
  • sysupgrade --archive=openipc.hi3516cv6xx-nor-ultimate.tgz -f -x -z:
    • image_combined=1do_update_firmware
    • Split combined image: FIT 2838817B -> kernel, remainder -> rootfs
    • FIT detected → Kernel updated to n/a (FIT), flashcp -vmtd2 44/44 blocks
    • rootfs losetup+mount OK → flashcp -vmtd3 114/114 blocks
    • post-flash: mtd2[0]=d00dfeed (FIT), mtd3[0]=hsqs (squashfs) ✅
  • firstboot: overlay wipe on mtd4 (60 blk) ✅

Two small notes

  1. fw_printenv isn't inherently broken under QEMU — with a working flash model the ev300 run reads soc fine (SoC hi3516ev300). The blank-soc path 1.0.53 now survives triggers when the env partition is empty/unwritten, which is the right thing to be defensive about — so the change is well justified; the "(it also fails under QEMU)" comment is just slightly imprecise.
  2. Pre-existing cosmetic (not introduced here): get_kernel_version uses date "+FMT" @<ts>, which busybox date rejects (date: can't set date: Invalid argument). Harmless; present in 1.0.52 too.

🤖 Generated with Claude Code

…comment)

Follow-up to the cross-agent QEMU validation of this branch (hi3516ev300 split +
hi3516cv610 combined, both pass):

- get_kernel_version: display the uImage epoch with `date -d @seconds "+FMT"`.
  A bare positional `@SECONDS` is treated by busybox as a clock-SET request
  ("date: can't set date: Invalid argument") and prints nothing, which would
  make compare_versions see two empty strings and wrongly skip the kernel
  update. (Pre-existing since 1.0.52; the `@seconds` form is only valid after
  -d per busybox 1.36.1 coreutils/date.c.)
- get_system_info: tighten the comment — fw_printenv returns nothing when the
  U-Boot env partition is empty/unwritten (not "fails under QEMU"; with a
  populated env it reads soc fine).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@widgetii widgetii merged commit 07d544e into master Jun 7, 2026
97 checks passed
@widgetii widgetii deleted the feat/sysupgrade-build-platform-soc-alias branch June 7, 2026 11:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant