sysupgrade: NAND user-data preservation + SquashFS-on-UBI for HiSilicon#2022
sysupgrade: NAND user-data preservation + SquashFS-on-UBI for HiSilicon#2022
Conversation
The HiSilicon NAND build shipped a single read-write UBIFS rootfs volume, which gives sysupgrade nothing to preserve and forces a destructive flash of the whole UBI MTD. Other NAND vendors (sigmastar, rockchip) already ship the upstream-recommended layout: a read-only SquashFS rootfs in one UBI volume and a writable UBIFS rootfs_data volume that holds the overlay and is left intact across upgrades. This commit aligns HiSilicon with that layout: - New ubinize_hisilicon.cfg: rootfs vol pointing at rootfs.squashfs and rootfs_data with vol_flags=autoresize. The default ubinize.cfg is left alone so rockchip rv1109/rv1126 (which still consume it) keep working. - Eight ultimate-NAND HiSilicon defconfigs (av100/av200/cv300/dv100, ev200/ev300, hi3518 ev200/ev300) repointed at the new cfg. - BR2_PACKAGE_MTD=y added to the same defconfigs so the firmware ships ubiformat — the only safe primitive for rewriting a UBI MTD without hitting the autoresize/image_seq trap that nandwrite triggers. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous reconstruction kept only a hardcoded list of keys (mem, console, panic, rootfstype, root, init, mtdparts, mmz_*) and silently stripped anything else. ubi.mtd= and ubi.block= — required for SquashFS-on-UBI boot — were among the casualties, so on the first post-upgrade boot of an ev200/ev300/hi3518ev300 camera load_hisilicon would call set_allocator and erase the migrated bootargs. Switch to additive form: filter out only mem=/mmz_allocator=/mmz= (the keys this script owns) and pass everything else through unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Existing NAND sysupgrade was destructive: every -r wiped the entire UBI
MTD and the overlay with it. Adopt OpenWrt's nand.sh pattern and let
HiSilicon NAND survive upgrades the same way NOR does.
Flow on a NAND camera with ubiformat available (= post-this-PR firmware):
1. Build a tarball of /etc/passwd, /etc/dropbear, /etc/network,
/etc/majestic.yaml, /root, ... — defaults plus anything in
/etc/sysupgrade.conf or /lib/upgrade/keep.d/*.
2. Compute migrated bootargs (root=/dev/ubiblock0_0 rootfstype=squashfs
ubi.block=0,0 ubi.mtd=N,2048). Idempotent — empty result if already
migrated.
3. Pivot to a tmpfs new-root carrying busybox, ubiformat, fw_setenv,
/etc/fw_env.config, the new rootfs.ubi, and the user-data tarball.
4. ubidetach + 'ubiformat -y -f rootfs.ubi /dev/mtdN'. ubiformat is
the only primitive that handles erase-counter preservation and
writes a single fresh image_seq across every PEB, including the
ones autoresize will later claim. nandwrite fails this on reboot
with 'bad image sequence number' panics.
5. fw_setenv bootargs (post-flash, so a flash failure cannot brick
the env).
6. ubiattach, wait for autoresize to materialise rootfs_data, mount
it, drop /sysupgrade.tgz, ubidetach, reboot.
On first boot of the new firmware /init mounts rootfs_data, finds the
tarball, extracts it onto the overlay upper, removes the file, and
proceeds normally.
Existing UBIFS-rootfs cameras have no ubiformat. For that one-time
hop we fall back to flash_eraseall+nandwrite (the path PR #2012
introduced) and warn that user data is erased; subsequent upgrades on
the new firmware preserve it.
The previous PR-#2012 'overlay erased' warning is dropped — overlay is
preserved by default now. -n / --wipe_overlay opts in to wiping (it
skips the tarball step so rootfs_data is left empty after flash).
Other changes:
- general/overlay/init: regex broadened to also enter the UBI overlay
branch on squashfs+ubi.block= cmdlines, and a one-shot
/overlay/sysupgrade.tgz extractor added. The tarball is rm -f'd
after extraction so subsequent boots are no-ops.
- general/overlay/etc/sysupgrade.conf: new empty file so users can
drop additional paths to preserve without modifying the upgrader.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Real-world hi3516av200 NAND upgrade exposed several issues in the preserve-user-data path that the prior commits did not catch: - Bootargs migration must also add init=/init. Without it, the kernel boots /sbin/init from squashfs directly and skips the overlayfs pivot — leaving / read-only and breaking everything that needs to write to /etc. - busybox tar has no -z support; piping through gzip explicitly fixes both the keep-list creation (sysupgrade) and the legacy first-boot extraction (init). - Run flash_eraseall before ubiformat so blocks UBI previously marked bad get force-erased and ubiformat does not skip them, which would otherwise leave stale EC headers with old image_seq and panic the kernel on next attach. - Mirror the post-pivot script's stdout to /dev/console so the UART log captures it; otherwise the entire flash phase is invisible. - Stage user-data directly into rootfs_data:/root (the overlayfs upper layer) via tar -xf instead of writing a single tarball file the busybox shell can not create on a freshly-mounted UBIFS volume. This makes /init's extraction hook redundant, so drop it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
End-to-end test results on hi3516av200 NANDTested on a real hi3516av200 NAND camera via UART + SSH. The fix-up commit ( Working ✅
Known limitation The post-pivot UBIFS write that stages The script logs Recommended follow-up Drop the post-pivot UBIFS write entirely and switch to Net effect of this PR Even with the known limitation, this PR is a strict improvement over PR #2012:
Brick recovery via U-Boot TFTP |
The previous tarball-into-rootfs_data approach hit EINVAL writing files
through the busybox shell on the post-pivot tmpfs UBIFS mount. Switch
to the cleaner pattern: update only the rootfs UBI volume in place via
ubiupdatevol, leaving rootfs_data (and the overlay it backs) entirely
untouched.
End-to-end verified on hi3516av200 NAND:
- root password set on running camera survives the upgrade,
- /root/canary.txt and /opt/marker.txt persist,
- /etc files modified through the overlay persist,
- kernel rebuilds and reboots into the new build (uname -r shows the
new SMP build number),
- rootfs_data UBI volume keeps its 655-LEB autoresized size and its
image_seq across the upgrade.
Implementation:
- Makefile: NAND release tarball now also ships rootfs.squashfs.${soc}
(extra-file slot added to PREPARE_REPACK / REPACK_FIRMWARE).
- sysupgrade picks one of three modes for do_update_rootfs_nand:
updatevol — when rootfs.squashfs is present in /tmp AND rootfs_data
already exists. ubidetach + ubiattach + ubiupdatevol on
/dev/ubi0_0. Fastest, preserves rootfs_data by
construction.
ubiformat — first-hop migration from legacy UBIFS-rootfs firmware
to the new layout. Full UBI MTD rewrite (destructive
for rootfs_data, which does not yet exist on legacy
cameras anyway).
legacy — pre-this-PR firmware that does not ship mtd-utils;
flash_eraseall + nandwrite. Same one-time destruction
as ubiformat path; subsequent upgrades hit updatevol
and preserve.
- The build_keep_list helper and /etc/sysupgrade.conf overlay file are
dropped — the whole rootfs_data volume survives, so an explicit
keep-list is not needed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Update: user data preservation now works end-to-end ✅Following maintainer review and the prior comment's recommended follow-up, switched to the single-volume update pattern: ubiupdatevol on This sidesteps every UBIFS write quirk hit on the previous attempt and preserves user data by construction rather than by tarball stash. What changed in commit
|
Why
#2012 added basic NAND support to
sysupgradebut every-rwiped the entire UBI MTD and the user's overlay with it. The maintainer's review captured the dilemma:This PR takes the "do it properly" path. The changes here let a NAND camera survive
sysupgrade -rwith config intact, the same way NOR cameras already do — and they bring the HiSilicon NAND firmware in line with the architecture sigmastar/rockchip already use.Two coupled root causes need to be fixed together; neither stands on its own:
flash_eraseall + nandwriteon a UBI MTD leaves UBI's autoresize unable to reclaim tail PEBs cleanly. On reboot the kernel panics withbad image sequence number in PEB N. That brick is reproducible on this branch — see the recovery write-up below.ubinize.cfgshipped a single read-write UBIFS rootfs volume, so even with a correct primitive there was no clean place to land preserved user data: any upgrade rewrote the same filesystem the user was editing.What this PR achieves
sysupgrade -ron NAND preserves user config across upgrades by default.-nopts in to wiping. (Same semantics as NOR.)rootfs_datafor the overlay — matching sigmastar (ubinize_sigmastar.cfg) and rockchip (ubinize_rockchip.cfg).sysupgradeusesubiformat -y -f(the OpenWrtnand.shpattern), which handles erase counters and writes one freshimage_seqacross every PEB. No moreimage_seqpanics.fw_setenv— runs after the flash succeeds so a flash failure can never leave the env pointing at a non-existent rootfs./etc/sysupgrade.confis a user-extensible keep-list (one path per line), mirroring OpenWrt.How it works
Reference: OpenWrt
package/system/procd/files/nand.sh.Upgrade steps for users
Online upgrade from a previous OpenIPC NAND camera
That's it. The script:
ubiformat,bootargsautomatically (root=ubi0:rootfs rootfstype=ubifs→root=/dev/ubiblock0_0 rootfstype=squashfs ubi.block=0,0),rootfs_data,After reboot, the new firmware's
/initextracts the tarball into the overlay and the camera comes up with config intact.To wipe overlay on upgrade (factory-reset semantics)
-nskips the keep-list step;rootfs_datais empty after the flash.Custom keep-list
Drop additional paths to preserve into
/etc/sysupgrade.conf(one path per line, files or directories):Migration from the legacy UBIFS-rootfs layout
Existing deployed cameras don't ship
ubiformat(it's introduced by this PR viaBR2_PACKAGE_MTD=y). The first hop from old → new firmware therefore runs the legacyflash_eraseall + nandwritepath. This single upgrade is destructive to user data (the script logs a clear warning). Every subsequent upgrade on the new firmware preserves correctly becauseubiformatis now installed.The bootargs migration is idempotent (a re-run on already-migrated env is a no-op), so it's safe to invoke from automation.
Recovery if something goes wrong
If the camera fails to boot after upgrade, U-Boot TFTP recovery still works:
urnandre-flashes the samerootfs.ubi.<soc>image; combined with this PR'subiformatsemantics it lands cleanly. The flash MTD partition is never touched until afterubiformatvalidates the input image, so a network/checksum failure during download cannot brick the camera.Scope
Out of scope (follow-ups)
CONFIG_MTD_UBI_GLUEBIfrom kernel configs — this PR removes sysupgrade's reliance on gluebi-exposed MTDs; unsetting the kconfig globally touches every NAND-capable kernel config and risks breaking unrelated consumers (notably the JFFS2-on-UBI fallback in/init).Files modified
general/scripts/ubifs/ubinize_hisilicon.cfgbr-ext-chip-hisilicon/configs/{hi3516av100,hi3516av200,hi3516cv300,hi3516dv100,hi3516ev200,hi3516ev300,hi3518ev200,hi3518ev300}_ultimate_defconfigBR2_PACKAGE_MTD=y(shipsubiformat)general/overlay/usr/sbin/sysupgradebuild_keep_list+compute_new_bootargshelpers;do_update_rootfs_nandrewritten to ubiformat + tarball patterngeneral/overlay/init/overlay/sysupgrade.tgzextractorgeneral/overlay/etc/sysupgrade.confgeneral/package/hisilicon-osdrv-hi3516ev200/files/script/set_allocatormem/mmz_allocator/mmzsoubi.mtd=/ubi.block=surviveload_hisiliconinvocationsTest plan
make BOARD=hi3516av200_ultimateproduces arootfs.ubi.hi3516av200whose first volume is SquashFS (verify withubinize -vorunubi)./root/canary.txt, edit/etc/majestic.yaml, append/optto/etc/sysupgrade.conf, drop/opt/marker.txt).sysupgradeto the camera; runsysupgrade -k -r --force_all; capture UART.bad image sequence numberpanic, root password persists,/root/canary.txtexists,/etc/majestic.yamlretains edits,/opt/marker.txtexists.ubinfo -ashows two volumes (rootfsSquashFS,rootfs_dataautoresized)./proc/cmdlineshowsroot=/dev/ubiblock0_0 rootfstype=squashfs.mountshowsoverlayfswithlowerdir=/andupperdir=/overlay.sysupgrade -k -r -n --force_allthen verify root password reset and/root/canary.txtgone.sysupgrade -k -r --force_all—fw_setenvis a no-op, bootargs unchanged.run urnandworks (kept compatible).