Repository navigation
upgrade: move a NOR camera to another layout, keeping its bootloader and settings - #247
Conversation
…and settings `upgrade` could already write a new layout over the running system, but on a lite-to-ultimate move (2 MB/5 MB to 3 MB/10 MB on 16 MB NOR) it would have bricked the camera it was most needed on: - The default bundle skipped partitions "boot" and "env" by name. A XiongMai flash calls the 64 KB after boot "wtf", the skip found nothing and said nothing, and the kernel went over it. - bootargs and bootcmd were regenerated, which drops what a vendor bootloader put there (an mmz carve-out, init=). - rootfs_data was never touched. After a repartition it starts in the middle of the old one, and jffs2 mounts the stale nodes. A bundle that names no prefix, offset or skip now: - keeps every partition in front of its first one (the kernel), as this flash names and sizes them. A XiongMai bootloader keeps its environment at 0x30000 inside "boot"; keeping only up to the environment wrote the kernel over "wtf" at 0x40000. - edits root=, mtdparts= and the kernel read's size in place (upgrade_env.c), and refuses before anything is stopped when it cannot find them. - writes the whole new rootfs_data. The settings go there as a jffs2 image (jffs2.c), taken once the old overlay is read-only and tried beforehand, so settings that will not fit are refused while nothing is stopped. --wipe-settings starts from defaults. - sets the U-Boot variables in the bundle's "env" object. Also: - A skip naming a partition the flash does not have is refused, not ignored. - The bundle is mapped, not read: in /tmp it would sit in RAM twice. - setenv matches the whole variable name: "bootcmd" no longer edits "bootcmdnor". - tools/upgrade_bundle.py --layout nor8m|nor16m builds such a bundle from a release .tgz. Tested on QEMU (hi3516ev300) with a full flash dump of a lab XiongMai 85H50AI on lite. One run of `ipctool upgrade` moved it to the 85H50AI ultimate image: u-boot read 3 MB at 0x50000, root on mtdblock3, ssh still took the old password, and every overlay file was byte-identical except the two rewritten on each boot (fake-hwclock, seedrng). boot and wtf were byte-identical. An oversize rootfs and 3 MB of settings were both refused with services running and the flash unchanged. --wipe-settings came up fresh: the customizer ran, then rebooted.
|
/review |
Code Review by Qodo
1.
|
…le env honest Four findings from review of the layout move: - A settings partition not found mounted was taken as one with nothing on it, and the move went ahead and erased it. The lookup now also knows "mtdN" and "mtd:rootfs_data", the other ways the kernel shows a jffs2 source. A rootfs_data it still cannot find mounted is refused unless --wipe-settings asks to start from defaults. - Extended attributes were counted and dropped. One of them is how overlayfs hides deleted files (trusted.overlay.opaque), so dropping it brings them back. An entry carrying any is now refused, with nothing written. Neither the QEMU run nor the lab camera had one. - The carried image could fill rootfs_data to the last block. jffs2 mounts that, then fails the first write with ENOSPC. Five erase blocks are now kept free for its garbage collection. - A bundle setting bootargs or bootcmd was reported as set and then replaced by the values upgrade writes for the new layout. Both keys are now refused, along with a non-string value, before anything is stopped. upgrade_bundle.py refuses them as -e too. jffs2_test covers the xattr refusal. QEMU, with the lab 85H50AI dump again: - the move still carries every setting (57 entries, 576 of 2752 KB); - a bundle setting bootcmd exits 2 with services running.
ipctool upgradecould already write a new partition layout over the running system. On a lite-to-ultimate move on 16 MB NOR (kernel 2 → 3 MB, rootfs 5 → 10 MB at a new offset) it would have bricked the camera it was most needed on.What was wrong
bootandenvby name. A XiongMai flash calls the 64 KB after bootwtf. The skip found nothing, said nothing, and the kernel went over it.bootargsandbootcmdwere regenerated, which drops what a vendor bootloader put there (an mmz carve-out,init=).What a bundle with no prefix, offset or skip now does
boot, so "keep up to the environment" is not enough.root=,mtdparts=and the size of the onesf readchange (src/upgrade_env.c). If it cannot find them, it refuses before anything is stopped.rootfs_datais written, with the settings in it as a jffs2 image (src/jffs2.c).--wipe-settingsstarts from defaults instead.envobject are set, e.g. theupgradeURL of the new firmware.tools/upgrade_bundle.py --layout nor8m|nor16m -f <release.tgz> [-e KEY=VALUE]makes one.Also
skipnaming a partition the flash does not have is refused, not ignored./tmpit would sit in RAM twice, about 10 MB more on a camera with about 40 MB available.setenvmatches the whole variable name, sobootcmdno longer editsbootcmdnor.add_mtdpartno longer readsdst[-1]on an empty prefix.upgrade_env_testandjffs2_testrun in pr-build-check.Tested
QEMU (
hi3516ev300), booting a full flash dump of a lab XiongMai 85H50AI on lite, its own bootloader included:ipctool upgrademoved it to an ultimate image. U-Boot read 3 MB at 0x50000, with root on mtdblock3.bootandwtfstayed byte-identical.Refusals, each with services still running and the flash unchanged:
rootfs_data.--wipe-settingscame up fresh: the customizer ran, then rebooted.The real camera, the same 85H50AI: migrated over ssh and back in 93 s, on the standard ultimate layout
256k(boot),64k(wtf),3072k(kernel),10240k(rootfs),-(rootfs_data), with the same results as QEMU.