v0.3.0 (2026-05-07)
/root (and /data via the existing symlink) is now persistent
across reboots, matching standard Nerves convention.
rootfs_data(UBI volume 5) is now mounted at/rootvia a small--pre-run-execscript (/usr/sbin/mount-data.sh). The script lazily formats the volume with UBIFS on first boot and falls back to tmpfs if the persistent mount can't be brought up, so the device always boots even with unhealthy NAND. Without this,/rootlived in the volatile rootfs (initramfs) and SSH host keys, NervesTime RTC drift fixes, etc. were regenerated on every reboot.mkfs.ubifs(BR2_PACKAGE_MTD_MKFSUBIFS=y) is now built into the target image so the lazy-format step works.nerves_fw_application_part0_devpath=/root(andfstype=ubifs,target=/root) is now baked into the U-Boot env, sonerves_motdresolves the data partition for its "Part usage" cell instead of falling back to "not available".
Backwards compatibility: existing v0.2.x installs upgrade cleanly.
The first boot of v0.3.0 formats rootfs_data (which was an empty
placeholder volume in v0.2.x). Rollback to v0.2.x is fine — the
older slot's initramfs ignores the UBIFS, runs in volatile mode.
v0.2.3 (2026-05-06)
Routine upstream bump.
nerves_system_br1.33.4 → 1.33.7- Erlang/OTP 28.4.1 → 28.5
- fwup 1.14.0 → 1.16.0
- Buildroot 2025.11.2 → 2025.11.3
No system-side changes required.
v0.2.2 (2026-04-09)
mix burn support via OpenWrt's NOR full-recovery mode.
mix burnnow prepares a FAT32 USB recovery stick that OpenWrt's SPI NOR recovery U-Boot can use to flash the entire SPI NAND — no serial console, no TFTP server, no typing of U-Boot commands. The stick contains the snand-preloader.bin (BL2) and ouropenwrt-one-nand.ubi(renamed tofactory.ubi). See README.md "Initial install" for the full procedure.- Ship
prebuilt/openwrt-one-snand-preloader.binfrom OpenWrt 24.10 (same source + license as the FIP). fwup.conf: replace the erroringcompletetask with one thatmbr_writes +fat_mkfses +fat_writes the recovery files. The .fw file grows by ~33 MiB (the .ubi) + 234 KiB (preloader) butmix burnnow Just Works with no per-app config.post-createfs.sh: stage the preloader into images/ so fwup can find it at firmware-build time.- README: document USB stick recovery as the primary initial-install path; serial + TFTP demoted to "alternative".
v0.2.1 (2026-04-08)
USB mass storage support.
- Linux: enable
CONFIG_SCSI,CONFIG_BLK_DEV_SD,CONFIG_USB_STORAGE,CONFIG_FAT_FS+CONFIG_VFAT_FS,CONFIG_EXFAT_FS, and the matching NLS tables (CP437,ISO8859-1,UTF-8). USB sticks now enumerate as/dev/sdNand FAT/exFAT partitions mount and read.
v0.2.0 (2026-04-08)
OTA + A/B slot support, kernel bump, several bug fixes that turned session-1 workarounds into proper fixes.
Added
- A/B FIT slots: UBI layout now uses
fit_a(vol 3) andfit_b(vol 4) instead of a singlefitvolume. Each slot is sized at 50 MiB. Active slot is selected at boot viafit_${nerves_fw_active}substitution inubi_read_production. - Image-level boot fallback: if
bootmfails on the active slot, U-Boot'sboot_productionflipsnerves_fw_active,saveenvs, and retries the other slot. - Bootcount-based runtime rollback: OTA sets
upgrade_available=1bootcount=0; U-Boot'snerves_count_attemptscript swaps slots oncebootcount > bootlimit(default 3).Nerves.Runtime.StartupGuardclears the counters once the app is healthy.
scripts/upload-ota.sh+scripts/apply-ota.exs: volume-level OTA via SFTP +ubiupdatevol+fw_setenv. Designed to be aliased asmix uploadfrom the user app.NervesSystemOpenwrtOne.UBootEnvKVBackend: customNerves.Runtime.KVBackendthat reads via the ErlangUBootEnvlibrary and writes via the Cfw_setenv(which issuesUBI_IOCVOLUP). Without this the default backend returns:epermon everyKV.putand breaksvalidate_firmware/0.- Full OpenWrt 24.10 default U-Boot env baked into ubootenv volumes
via
prebuilt/uboot-env-template.txt, with the0x1F000env size matchingCONFIG_ENV_SIZEin OpenWrt's mt7981 U-Boot. Eliminates the cosmeticboardid: U-boot environment CRC32 mismatchwarning that was caused by sizing our env smaller than what U-Boot writes back. CONFIG_IP_ADVANCED_ROUTER=y,CONFIG_IP_MULTIPLE_TABLES=y,CONFIG_IP_ROUTE_MULTIPATH=yso VintageNet's policy-routing setup doesn't crash withRTNETLINK answers: Operation not supported.
Changed
- Linux 6.12 → 6.18.12.
- SPI NAND driver path: dropped the
spi-mtk-snfiattempt and the Etron 0x77-shifted-manufacturer-ID workaround. Now usesspi-mt65xxwith the OpenWrt SPI calibration patch stack (patches 121, 330, 431-435, 930) plusmtk_bmt. The chip is actually a Winbond 256 MiB part, not the 128 MiB Etron we initially guessed. - U-Boot env path in
fw_env.config:/dev/ubi0_0and/dev/ubi0_1instead of/dev/ubi0:ubootenv. The Erlanguboot_envlibrary uses plainFile.openand doesn't understand the:volnameshorthand that fwup-tool'sfw_printenvaccepts.
Fixed
- mkimage invocation in
wrap-firmware.shnow prefers/usr/bin/mkimageover Buildroot's host build, because the latter ships withMKIMAGE_DTC=""and explodes withsh: 1: -I: not foundwhenever it tries to run dtc internally.
v0.1.0 (2026-04-07)
Initial Nerves system for the OpenWRT One.
- Linux 6.12 mainline kernel with small patches
- Custom DTS based on mainline
mt7981b-openwrt-one.dtswith full peripheral enablement - WiFi 2.4 / 5 GHz with proper calibration from factory partition
- Both Ethernet ports (1 GbE LAN + 2.5 GbE WAN with EN8811H PHY)
- RTC, GPIO watchdog, LEDs, buttons
- NAND boot via UBI volumes (fip + fit + ubootenv + rootfs_data)
- Pre-built FIP from official OpenWrt 24.10 release