Skip to content

nand: kernel inside the UBIFS rootfs, volumes sized by their images; retire the old NAND layouts - #2537

Merged
widgetii merged 3 commits into
masterfrom
nand/hisilicon-ubi-fit
Oct 4, 2026
Merged

widgetii merged 3 commits into
masterfrom
nand/hisilicon-ubi-fit

Conversation

@widgetii

@widgetii widgetii commented Oct 4, 2026

Copy link
Copy Markdown
Member

Follows OpenIPC/u-boot-xmedia#11, which boots a NAND kernel from the UBIFS rootfs and is now the bootloader for the hi3516ev200 family.

Layout

0x000000  boot 768K   u-boot-xmedia
0x0C0000  env  256K
0x100000  ubi  rest   rootfs       UBIFS, the kernel inside as /boot/fitImage
                      rootfs_data  overlay, everything else
  • No space reserved for a kernel. external.mk copies the kernel into the UBIFS image's own copy of the target tree. That is the FIT where the board builds one, otherwise the uImage; always exactly one file. The NOR squashfs is unchanged.
  • Volume sizes come from the image. ubinize-nand.cfg gives rootfs no vol_size, so the volume is exactly as big as its image, and rootfs_data takes the rest. The only size gate is rootfs.ubi at 24M, the RAM a fresh install stages it in.
  • NAND package contents: rootfs.ubifs, rootfs.ubi (fresh install), and fitImage as the SoC witness.

Boards

  • gk7205v500 family: moves to this layout from the separate-kernel-volume one introduced in gk7205v500 NAND: FIT kernel volume, CMA, and sysupgrade for UBI layouts #2526.
  • hi3516ev200 family (hi3516ev200, hi3516ev300, hi3518ev300): moves here from the retired split layout (uImage in a raw kernel partition).
    • New board/hi3516ev200/nand-fit.its names its DTB @DTB@, because each model builds its own <model>-demb.dtb.
    • rootfs_script.sh stamps the DTB name along with @SOC@.
  • hi3516av100, av200, dv100, cv300, hi3518ev200: stop building NAND images. None has a bootloader that can install or boot this layout. Their NOR images are unchanged.

sysupgrade

New layout (ubifs). An upgrade writes the one image and resizes the volumes to fit it. Running as PID 1 in the RAM root, it:

  1. copies the settings out of rootfs_data;
  2. removes that volume;
  3. resizes rootfs to the image (ubirsvol);
  4. writes the image;
  5. recreates rootfs_data on what is left (ubimkvol -m);
  6. puts the settings back.

Related behaviour:

  • -k means writing the rootfs, since the kernel lives in it.
  • -r -n skips the settings copy.
  • The room check counts both volumes, minus the settings being kept.

Retired layouts are refused before anything is downloaded or written, with a link to the reinstall instructions. This covers:

  • the split layout;
  • the separate-kernel-volume FIT layout;
  • squashfs over ubiblock.

-n on its own is still allowed. Without the split-layout refusal, sysupgrade wrote a NOR squashfs through gluebi over the mounted UBIFS volume and bricked the camera. Retired cameras still boot; only their upgrades are refused.

The offline harness passes 244 checks, including new scenarios for each of these paths.

Verified on a hi3516ev300 (W25N01GV NAND, 5 factory bad blocks)

  • Refusal. While the camera was still on the split layout, a run was refused: "retired split NAND layout … nothing was written", exit 1, /proc/mtd unchanged.
  • Install. Installed with the openipc.org NAND commands from u-boot-xmedia: rootfs.ubi written with nand write.trimffs. U-Boot loads /boot/fitImage from UBIFS with crc32+ sha1+ OK, and the kernel boots root=ubi0:rootfs.
  • Upgrades. sysupgrade -r from a local package, with a marker in the overlay, run twice:
    • First run: rootfs stayed at 155 LEBs.
    • Second run, with an image 2 MB smaller: rootfs shrank to 138 LEBs and rootfs_data was recreated on the rest.
    • The marker and the SSH key survived both runs.
    • Each run rebooted, and the camera came back booting the FIT.

Not covered on hardware: growing a volume (harness only), -n on this layout (harness only), and the gk7205v500 family on this layout (same code path, built in CI).

NAND images no longer set aside flash for a kernel. The UBI device now
holds two volumes:
- rootfs: UBIFS, with the kernel in it as /boot/fitImage (zImage + DTB,
  each hashed);
- rootfs_data: the overlay.
external.mk adds the kernel to the UBIFS image's own copy of the target
tree, so the NOR squashfs is unchanged. It is one file, never two: the FIT
where the board builds one, otherwise the uImage. u-boot-xmedia boots
either. ubinize-nand.cfg gives rootfs no vol_size, so the volume is
exactly as big as its image, and rootfs_data takes the rest.

The hi3516ev200 family (hi3516ev200, hi3516ev300, hi3518ev300) moves to
this layout from the retired split one (a uImage in a raw `kernel`
partition, UBIFS root beside it). Its nand-fit.its names the DTB as @dtb@,
since each model builds its own <model>-demb.dtb; rootfs_script.sh stamps
it alongside @soc@. hi3516av100, av200, dv100, cv300 and hi3518ev200 stop
building NAND images: none has a bootloader that can install or boot this
layout. Their NOR images are unchanged.

The NAND package carries rootfs.ubifs, rootfs.ubi for a fresh install, and
fitImage as the SoC witness. The only size gate is rootfs.ubi at 24M, the
RAM a fresh install stages it in; no volume bounds either image.

sysupgrade:
- ubifs layout (rootfs volume, no kernel volume, no kernel partition): an
  upgrade writes the one image and resizes the volumes to it. As PID 1 in
  the RAM root it copies the settings out of rootfs_data, removes that
  volume, resizes rootfs to the image, writes it, recreates rootfs_data on
  what is left and puts the settings back. -k means writing the rootfs,
  since the kernel is in it. -r -n skips the copy. The room checked is
  both volumes less the settings, not the old rootfs volume.
- The split layout is refused before anything is touched, kernel-only runs
  included. Without that refusal the MTD path flashcp'd a NOR squashfs
  through gluebi over the mounted UBIFS volume.
- The earlier layout with a separate kernel volume is refused the same
  way. Both refusals point at the reinstall instructions on openipc.org.
- ubiblock cameras are unchanged.

The offline harness covers all of it: 253 checks pass.

Verified on a hi3516ev300 (W25N01GV NAND, 5 factory bad blocks):
- Installed from u-boot-xmedia with the openipc.org commands: tftpboot
  rootfs.ubi, nand erase 0x100000 0x7f00000, nand write.trimffs.
- U-Boot loads /boot/fitImage from UBIFS, the hashes pass, and the kernel
  mounts root=ubi0:rootfs read-only, the UBIFS overlay read-write.
- sysupgrade -r from a local package, with a marker in the overlay:
  - the first run rewrote rootfs at the same 155 LEBs; the second, with an
    image 2 MB smaller, shrank it from 155 to 138 LEBs. Growing a volume is
    covered by the harness only;
  - rootfs_data was recreated each time on the rest (837 and 854 LEBs);
  - the marker and the SSH key survived both runs;
  - the camera rebooted each time and came back booting the FIT.
- The same camera, still on the split layout, refused an upgrade:
  "retired split NAND layout ... nothing was written", exit 1, /proc/mtd
  unchanged.
The squashfs-over-ubiblock layout keeps its kernel in a sized volume of its
own, as the first FIT layout does. It is retired the same way: a run that
would write either half is refused before anything is touched, with the
reinstall link. -n alone still empties the settings volume.

Also gone: the gluebi path an old ubiblock camera took when its inittab had
no ::restart: entry, and check_rootfs_format's ubiblock branch, which
nothing reaches now.

Images on the retired layout still boot; init keeps mounting their overlay.
Only upgrades are refused. A NAND camera upgrades from a -nand- package
only, which the ultimate builds of the hi3516ev200 and gk7205v500 families
ship. Harness: 244 checks pass.
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Boot NAND kernels from UBIFS and retire unsafe upgrade layouts

✨ Enhancement 🐞 Bug fix ⚙️ Configuration changes 🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Package the kernel inside UBIFS and size NAND volumes to the rootfs image.
Diagram

graph TD
  A{"NAND layout?"} -->|retired| B["Refuse upgrade"]
  A -->|supported| C["Rootfs upgrade"] --> D["PID 1 handoff"] --> E["Back up settings"] --> F["Resize and write"] --> G["Restore overlay"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Keep fixed-size UBI volumes
  • ➕ Avoids removing and recreating rootfs_data during each upgrade.
  • ➖ Reserves flash for a separate kernel or fixed rootfs ceiling.
  • ➖ Cannot accommodate rootfs growth beyond that ceiling.
2. Require U-Boot reinstall for every NAND update
  • ➕ Avoids in-place volume restructuring and its settings-loss window.
  • ➖ Eliminates normal remote sysupgrade for supported cameras.
  • ➖ Requires operator access to the bootloader.

Recommendation: Use the proposed in-place resize for cameras already on the new layout and require reinstall for retired layouts. It preserves remote upgrades without retaining fixed volume ceilings, while refusing migrations that cannot safely use the existing flash layout.

Files changed (17) +402 / -165

Enhancement (3) +89 / -3
nand-fit.itsAdd per-model FIT definition for hi3516ev200 NAND +55/-0

Add per-model FIT definition for hi3516ev200 NAND

• Defines a FIT containing a hashed zImage and model-specific DTB. Provides SoC and DTB placeholders for stamping during the build.

br-ext-chip-hisilicon/board/hi3516ev200/nand-fit.its

external.mkEmbed one kernel file in the UBIFS image +26/-0

Embed one kernel file in the UBIFS image

• Adds a UBIFS pre-generation hook for FIT-enabled NAND boards that copies fitImage, or falls back to uImage, into /boot. The hook targets UBIFS generation rather than the NOR squashfs.

general/external.mk

rootfs_script.shStamp model-specific DTBs into NAND FITs +8/-3

Stamp model-specific DTBs into NAND FITs

• Substitutes both SoC and DTB placeholders before collecting FIT inputs. Reads DTB filenames from the stamped ITS so hi3516ev200-family models package their own generated DTB.

general/scripts/rootfs_script.sh

Bug fix (1) +166 / -42
sysupgradeResize UBIFS volumes and refuse retired NAND upgrades +166/-42

Resize UBIFS volumes and refuse retired NAND upgrades

• Adds a shared-space fit check and a RAM-root upgrade sequence that backs up settings, rebuilds volumes around the new image, and restores the overlay. Treats -k as a rootfs update on the new layout and refuses split, separate-kernel-volume, and ubiblock upgrades before download or writing.

general/overlay/usr/sbin/sysupgrade

Tests (1) +99 / -67
test_sysupgrade.shExercise new NAND upgrades and retired-layout refusals +99/-67

Exercise new NAND upgrades and retired-layout refusals

• Extends UBI and mount stubs to track volume restructuring and settings restoration. Replaces old kernel-volume write expectations with refusal checks and tests the new upgrade order, image-fit check, -k behavior, and overlay wipe paths.

.github/scripts/test_sysupgrade.sh

Documentation (1) +3 / -2
nand-fit.itsDocument the FIT's new location in UBIFS +3/-2

Document the FIT's new location in UBIFS

• Clarifies that the generated FIT is installed at /boot/fitImage rather than packed into a separate kernel volume.

br-ext-chip-goke/board/gk7205v500/nand-fit.its

Other (11) +45 / -51
MakefileGate NAND install images at 24 MiB +10/-7

Gate NAND install images at 24 MiB

• Removes fixed kernel and UBIFS volume-size checks for FIT NAND packages. Limits rootfs.ubi to the RAM staging capacity used during fresh installation.

Makefile

ubinize-nand.cfgRemove the gk7205v500 kernel volume +9/-16

Remove the gk7205v500 kernel volume

• Defines an image-sized UBIFS rootfs as volume 0 and an autoresizing rootfs_data overlay as volume 1. Removes the dedicated FIT volume and fixed rootfs size.

br-ext-chip-goke/board/gk7205v500/ubinize-nand.cfg

ubinize-nand.cfgDefine the hi3516ev200 two-volume NAND layout +23/-0

Define the hi3516ev200 two-volume NAND layout

• Adds an image-sized UBIFS rootfs volume containing the kernel and an autoresizing rootfs_data overlay. Replaces the family's former raw-kernel-partition packaging.

br-ext-chip-hisilicon/board/hi3516ev200/ubinize-nand.cfg

hi3516av100_ultimate_defconfigStop building hi3516av100 NAND images +0/-5

Stop building hi3516av100 NAND images

• Removes UBI and UBIFS image settings while retaining the NOR squashfs configuration.

br-ext-chip-hisilicon/configs/hi3516av100_ultimate_defconfig

hi3516av200_ultimate_defconfigStop building hi3516av200 NAND images +0/-5

Stop building hi3516av200 NAND images

• Removes UBI and UBIFS image settings while retaining the NOR squashfs configuration.

br-ext-chip-hisilicon/configs/hi3516av200_ultimate_defconfig

hi3516cv300_ultimate_defconfigStop building hi3516cv300 NAND images +0/-5

Stop building hi3516cv300 NAND images

• Removes UBI and UBIFS image settings while retaining the NOR squashfs configuration.

br-ext-chip-hisilicon/configs/hi3516cv300_ultimate_defconfig

hi3516dv100_ultimate_defconfigStop building hi3516dv100 NAND images +0/-5

Stop building hi3516dv100 NAND images

• Removes UBI and UBIFS image settings while retaining the NOR squashfs configuration.

br-ext-chip-hisilicon/configs/hi3516dv100_ultimate_defconfig

hi3516ev200_ultimate_defconfigSelect the new hi3516ev200 NAND layout +1/-1

Select the new hi3516ev200 NAND layout

• Points UBI image generation to the family's new two-volume ubinize configuration.

br-ext-chip-hisilicon/configs/hi3516ev200_ultimate_defconfig

hi3516ev300_ultimate_defconfigSelect the new hi3516ev300 NAND layout +1/-1

Select the new hi3516ev300 NAND layout

• Points UBI image generation to the hi3516ev200 family's new two-volume ubinize configuration.

br-ext-chip-hisilicon/configs/hi3516ev300_ultimate_defconfig

hi3518ev200_ultimate_defconfigStop building hi3518ev200 NAND images +0/-5

Stop building hi3518ev200 NAND images

• Removes UBI and UBIFS image settings while retaining the NOR squashfs configuration.

br-ext-chip-hisilicon/configs/hi3518ev200_ultimate_defconfig

hi3518ev300_ultimate_defconfigSelect the new hi3518ev300 NAND layout +1/-1

Select the new hi3518ev300 NAND layout

• Points UBI image generation to the hi3516ev200 family's new two-volume ubinize configuration.

br-ext-chip-hisilicon/configs/hi3518ev300_ultimate_defconfig

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Sparse settings can run out of restore space ✓ Resolved
Description
ubifs_rootfs_room reserves overlay_kb from df as though allocated blocks equal the space
needed to extract the settings archive. When the overlay contains sparse files, extraction can need
substantially more space than df counted, so an accepted rootfs image can leave rootfs_data too
small and restoration fails after the rootfs is written.
Code

general/overlay/usr/sbin/sysupgrade[R179-181]

+	[ -n "$ubi_data_dev" ] && debs=$(cat "$d/reserved_ebs" 2>&3 || echo 0)
+	[ "1" = "$clear_overlay" ] || keep=$((${overlay_kb:-0} * 1024))
+	echo $(((ebs + debs - UBIFS_OVERLAY_MIN_LEBS) * usable - keep))
Evidence
overlay_kb is taken from df used blocks and subtracted in the room check. Settings are restored
with tar -xf into a newly created volume, and extraction failure is only warned about after the
old settings volume has been removed.

general/overlay/usr/sbin/sysupgrade[2144-2149]
general/overlay/usr/sbin/sysupgrade[175-192]
general/overlay/usr/sbin/sysupgrade[225-245]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new image-space check uses allocated overlay blocks, which can undercount the space required to restore sparse files from the settings archive.
## Fix Focus Areas
- general/overlay/usr/sbin/sysupgrade[175-192]
- general/overlay/usr/sbin/sysupgrade[216-245]
- general/overlay/usr/sbin/sysupgrade[2144-2149]
## Recommended Fix
Before destructive volume changes, measure or conservatively bound the space required by the files as they will be extracted, and reject rootfs images that cannot leave that space for `rootfs_data`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Settings wiped silently when backup fails ✓ Resolved
Description
rewrite_ubifs falls through to ubirmvol when the read-only rootfs_data mount fails or tar
cannot complete the settings backup, leaving no usable archive to restore. On a routine `sysupgrade
-r, an unreadable overlay or one too large for the RAM-backed /tmp` can therefore leave the camera
with an empty settings volume, even though a rootfs-only upgrade previously left rootfs_data
untouched.
Code

general/overlay/usr/sbin/sysupgrade[R219-226]

+			if mount -t ubifs -o ro "$name:rootfs_data" "$mnt" 2>&3; then
+				tar -C "$mnt" -cf "$bak" . 2>&3 ||
+					{ echo_c 33 "Warning: could not copy the settings; they will be reset."; rm -f "$bak"; }
+				busybox umount "$mnt" 2>&3
+			fi
+		fi
+		set_progress ubirmvol "$ubi" -N rootfs_data ||
+			die "Removing the settings volume failed."
Evidence
The read-only mount has no failure branch, and the tar failure branch removes the partial archive
but continues to ubirmvol. Restoration later runs only if the archive exists. The script documents
that /tmp is RAM-backed and already holds the unpacked image; although the room check accounts for
overlay_kb, it does not verify that /tmp can hold the backup.

general/overlay/usr/sbin/sysupgrade[216-227]
general/overlay/usr/sbin/sysupgrade[2146-2149]
general/overlay/usr/sbin/sysupgrade[216-245]
general/overlay/usr/sbin/sysupgrade[1008-1014]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`rewrite_ubifs` removes `rootfs_data` even when settings retention was requested but the volume could not be mounted or completely archived. A failed mount produces no message, and an archive failure produces only a warning before the settings volume is removed.
## Fix Focus Areas
- general/overlay/usr/sbin/sysupgrade[216-227]
## Recommended Fix
When settings retention is requested, require a successful read-only mount, complete archive, and unmount before calling `ubirmvol`. If any backup step fails, call `die` with a clear message before modifying flash; the PID 1 die path can then reboot into the untouched system. Keep `-n` as the explicit settings-reset path. Before archiving, also consider comparing `overlay_kb` with free space in `/tmp`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Squashfs-over-UBI cameras can no longer upgrade ✓ Resolved
Description
This PR marks the ubiblock layout (a kernel UBI volume plus a squashfs rootfs volume, booted
root=/dev/ubiblock) as retired, and dies on any kernel or rootfs update for it. The PR also
deletes the gluebi fallback those cameras used before the hand-off. The rockchip rv1103/rv1106 and
sigmastar ssc325de/ssc337de/ssc338q NAND images are still built from exactly this volume layout, and
their packages carry only rootfs.ubi, so a camera that boots them through ubiblock has no new layout
to reinstall into and can never upgrade again.
Code

general/overlay/usr/sbin/sysupgrade[R2677-2681]

+case "$ubi_layout" in ubifs-kvol|ubiblock)
+	if [ "1" = "$update_kernel" ] || [ "1" = "$update_rootfs" ]; then
+		die "This camera uses the retired NAND layout with a separate kernel volume; current images carry the kernel inside the rootfs. Reinstall it from U-Boot with the current NAND instructions: https://openipc.org/cameras/vendors/$vendor/socs/$model -- nothing was written."
+	fi ;;
+esac
Evidence
detect_ubi_layout sets ubiblock for any camera that has a kernel volume and root=/dev/ubiblock,
whatever the vendor. ubinize_sigmastar.cfg and ubinize_rockchip.cfg create a kernel volume
(uImage/zboot.img) and a squashfs rootfs volume, which is the layout the old comment described as
ubiblock. The Makefile still packages rootfs.ubi for these vendors and builds no ubifs-in-rootfs
image for them. init still mounts the overlay for root=/dev/ubiblock command lines. Whether a
given board boots ubiblock depends on its U-Boot environment, which is not in this repo, but the PR
retires the layout for every vendor, not only gk7205v500.

general/scripts/ubifs/ubinize_sigmastar.cfg[1-31]
general/scripts/ubifs/ubinize_rockchip.cfg[1-31]
Makefile[194-195]
general/overlay/init[86-94]
general/overlay/usr/sbin/sysupgrade[2204-2207]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The ubiblock refusal applies to every vendor, but only the gk7205v500 and hi3516ev200 families have a replacement layout. Sigmastar and rockchip NAND images are still ubiblock-shaped.
## Fix Focus Areas
- general/overlay/usr/sbin/sysupgrade[2677-2681]
- general/overlay/usr/sbin/sysupgrade[2204-2207]
## Recommended Fix
Refuse ubiblock only for vendors or SoCs whose builds moved to the in-rootfs kernel layout (goke gk7205v500 family, hisilicon hi3516ev200 family). Keep the previous ubiblock write path (the kernel volume written in place, the rootfs through the hand-off) for everything else.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View medium (1)
4. A supplied kernel file is silently ignored ✓ Resolved
Description
On the ubifs layout, --kernel=FILE is turned into update_kernel=0 update_rootfs=1, but
rootfs_file stays empty. rootfs_image then falls back to /tmp/rootfs.ubifs.$model, and the
user's file is only read as the SoC witness. A plain --kernel=FIT run either dies with "No rootfs
image" or flashes whatever stale /tmp/rootfs.ubifs.$model is lying around, and it never installs
the kernel the operator passed.
Code

general/overlay/usr/sbin/sysupgrade[R2684-2688]

+if [ "$ubi_layout" = "ubifs" ] && [ "1" = "$update_kernel" ]; then
+	update_kernel=0
+	update_rootfs=1
+	echo_c 37 "\nThe kernel lives inside the rootfs on this camera: writing the rootfs."
+fi
Evidence
--kernel=* sets only update_kernel and kernel_file, not remote_update, so nothing is
downloaded. rootfs_image returns /tmp/rootfs.ubifs.$model when rootfs_file is empty, and
preflight_image_sizes and do_update_rootfs write that path. verify_ubifs_rootfs uses
kernel_image (the user's file) only for fit_soc.

general/overlay/usr/sbin/sysupgrade[152-161]
general/overlay/usr/sbin/sysupgrade[2488-2493]
general/overlay/usr/sbin/sysupgrade[563-571]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
On the ubifs layout, a local `--kernel=FILE` is converted into a rootfs write that ignores FILE and writes a default /tmp path.
## Fix Focus Areas
- general/overlay/usr/sbin/sysupgrade[2684-2688]
## Recommended Fix
When `ubi_layout=ubifs`, `kernel_file` is set, `rootfs_file` is empty and `remote_update` is not 1, die with a message saying the kernel lives inside rootfs.ubifs and must be supplied with `--rootfs=`. Only remap `-k` (remote) to a rootfs write.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

5. Split-layout refusal links to the HiSilicon page for any vendor ✓ Resolved
Description
is_split_nand matches any vendor: a UBIFS root, no kernel UBI volume, and a raw kernel MTD
partition. Its die message hardcodes https://openipc.org/cameras/vendors/hisilicon/socs/$model,
while the kvol refusal next to it uses $vendor. A non-HiSilicon NAND camera that matches is sent
to a reinstall page that does not exist.
Code

general/overlay/usr/sbin/sysupgrade[R2671-2673]

+if { [ "1" = "$update_kernel" ] || [ "1" = "$update_rootfs" ]; } && is_split_nand; then
+	die "This camera uses the retired split NAND layout (kernel in its own partition, UBIFS root beside it), which this upgrade cannot write safely. Reinstall it from U-Boot with the current NAND instructions: https://openipc.org/cameras/vendors/hisilicon/socs/$model -- nothing was written."
+fi
Evidence
is_split_nand has no vendor check, and the URL in the split-layout die message is hardcoded to
hisilicon, unlike the ubifs-kvol message a few lines below.

general/overlay/usr/sbin/sysupgrade[2220-2225]
general/overlay/usr/sbin/sysupgrade[2677-2681]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The split-layout refusal hardcodes the hisilicon vendor in its reinstall URL.
## Fix Focus Areas
- general/overlay/usr/sbin/sysupgrade[2671-2673]
## Recommended Fix
Replace `vendors/hisilicon/` with `vendors/$vendor/`, as the ubifs-kvol message does.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can describe a rule in plain language on the Rules page and Qodo drafts it for you

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread general/overlay/usr/sbin/sysupgrade
Comment thread general/overlay/usr/sbin/sysupgrade Outdated
Comment thread general/overlay/usr/sbin/sysupgrade Outdated
Comment thread general/overlay/usr/sbin/sysupgrade
Review on #2537.

- ubiblock is retired only on the SoCs whose NAND images moved to the
  kernel-in-rootfs layout: gk7205v500, v510, v530, hi3516ev200, hi3516ev300,
  hi3518ev300 and hi3516dv200 (nand_layout_moved). SigmaStar and Rockchip
  NAND images are still ubiblock-shaped, so everywhere else the ubiblock
  write path stays: the kernel volume is written in place, the rootfs goes
  through the hand-off, and old-inittab cameras keep the gluebi fallback.
- Keeping the settings on an upgrade now has to work before anything
  changes. If the read-only mount or the copy into RAM fails, the run stops
  with nothing written, and -n remains the way to upgrade without the
  settings. The archive's real size, which counts sparse files at full
  length, is then checked against the room beside the new image before the
  first volume operation.
- --kernel=FILE alone on the ubifs layout is refused: the kernel lives
  inside rootfs.ubifs and has to come with --rootfs=. Previously the run
  wrote whatever rootfs was at the default path. A remote -k still becomes
  a rootfs write.
- The split-layout refusal links to the camera's own vendor page, not
  always hisilicon's.

Harness: 257 checks pass. New cases: ubiblock writes on ssc338q, ubiblock
refused on gk7205v500 with and without ::restart:, --kernel alone
refused, and unreadable settings stopping stage 2 before any volume is
touched.
@widgetii
widgetii merged commit f8fc1f0 into master Oct 4, 2026
134 checks passed
@widgetii
widgetii deleted the nand/hisilicon-ubi-fit branch October 4, 2026 15:44
widgetii added a commit to OpenIPC/defib that referenced this pull request Oct 4, 2026
The u-boot-xmedia SoCs (hi3516ev200/ev300/dv200, hi3518ev300,
gk7205v500/v510/v530) moved to one NAND layout. It landed in
OpenIPC/u-boot-xmedia#11 and #12, OpenIPC/firmware#2537, and
OpenIPC/website#392 and #393:

```
0x000000 boot 768K   u-boot-<soc>-nand.bin
0x0C0000 env  256K
0x100000 ubi  rest   rootfs.ubi.<board>: UBIFS rootfs (kernel inside, /boot/fitImage) + rootfs_data
```

defib still installed the retired split layout on these SoCs and
downloaded the retired `-universal` bootloader for them.

## Install (`install --nand`)

For these SoCs `install --nand` now:
- writes `u-boot-<soc>-nand.bin` into 0..0xc0000;
- writes `rootfs.ubi.<board>` with `nand erase.part ubi` and `nand
write.trimffs`, then reads it back and CRC-checks it;
- runs `env default -a`, restores the MAC, and saves.

**Never sent:** `setenv mtdparts`, `mtdids`, `bootcmd`, `bootargs`, or
`ubi part`/`create`/`write`.

**Kernel and `rootfs-data` stages:** no-ops. The kernel and an empty
`rootfs_data` are inside the UBI image.

**Erase safety:**
- The installer checks that `mtdparts` puts `ubi` at 0x100000 before
erasing.
- It falls back to `nand erase 0x100000` (to the chip end) where
`erase.part` is unavailable.
- Other chips keep the split-layout path.

## Bootloader names

These seven SoCs resolve per flash type, to `u-boot-<soc>-nor.bin` or
`u-boot-<soc>-nand.bin`.
- `install` follows `--nand`. `burn` gains `--nand` and defaults to NOR.
`restore --flash-type` follows the flash type.
- The `-universal` image is never downloaded for them, and a stale
cached one doesn't stand in for the new build.
- Every other chip is unchanged.

## Web UI

- Takes the `-nor` build for these SoCs.
- Now cuts the SPL where the compressed payload starts (`detectSplSize`,
a port of `HiSiliconStandard._detect_spl_size`). The u-boot-xmedia
images put it at 0x4400, while the profile says 0x6000. Sending the
profile length writes into SRAM the boot ROM uses for its own state.

## Verified

On a hi3516ev300 (W25N01GV, 128 MiB, 5 factory bad blocks), `defib
install -c hi3516ev300 --nand --power-cycle` with the NAND package and
the u-boot-xmedia master NAND image ran end to end:
- burned U-Boot to RAM from the boot ROM;
- `U-Boot OK`;
- `Erased ubi: 0x100000, 0x7F00000 bytes`;
- `Flash verified: E2E60EAA`;
- `Restoring factory ethaddr`, `Environment saved`;
- rebooted into OpenIPC, which booted `/boot/fitImage` and came up on
the network.

Separately, `defib burn -c hi3516ev300 -f u-boot-hi3516ev300-nand.bin`
loaded the u-boot-xmedia image from the boot ROM; defib found its gzip
SPL boundary at 0x4400.

## Tests

- pytest: 1020 passed. ruff and mypy clean.
- New `tests/test_nand_ubi_install.py`: the exact console sequence, the
erase fallback, the missing-`mtdparts` path, refusing a relocated `ubi`,
an env-only run, and a NOR install taking `-nor` over a cached
`-universal`.
- `tests/test_firmware.py` covers names per flash type.
- Web tests: 92 pass. The new `detectSplSize` gives 0x4400 on the real
hi3516ev300 image.

## Not verified on hardware

- The gk7205v5xx and hi3516dv200 paths.
- The Web UI recovery with the `-nor` images.
- The `erase.part` fallback on a U-Boot without it.
widgetii added a commit to OpenIPC/u-boot-hi3516ev200 that referenced this pull request Oct 4, 2026
hi3516ev200, hi3516ev300 and hi3518ev300 now boot the bootloader
OpenIPC/u-boot-xmedia builds (#11 there). It publishes them per flash type
as u-boot-<soc>-nor.bin and u-boot-<soc>-nand.bin, and carries the
UBI-only NAND layout the firmware installs (OpenIPC/firmware#2537).
openipc.org and defib take those now.

The publish job would keep overwriting u-boot-<soc>-universal.bin in the
OpenIPC/firmware release with a build nothing should load, so it goes.
The build and the QEMU smoke test stay as CI for this tree.
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