A Nerves.Runtime.KVBackend for boards whose U-Boot environment lives in
UBI volumes on raw NAND/NOR flash.
Why?
Writing to a UBI volume character device (/dev/ubi0_N) requires the
UBI_IOCVOLUP ioctl to enter atomic-update mode. Plain pwrite/2 —
used by Erlang's :file module and the default
Nerves.Runtime.KVBackend.UBootEnv — returns EPERM. So the stock
Nerves backend can't write the U-Boot env on UBI-backed systems, and
Nerves.Runtime.validate_firmware/0 fails with {:error, :eperm},
which in turn breaks Nerves.Runtime.StartupGuard.
This backend reads through the Erlang UBootEnv library (pread/3
works fine on /dev/ubi*) and writes by shelling out to the C
fw_setenv tool from u-boot-tools, which issues the
UBI_IOCVOLUP ioctl transparently.
Requirements
The Nerves system / target must provide:
/etc/fw_env.configpointing at the UBI volumes holding the env. Per-volume paths only (e.g./dev/ubi0_0), not the/dev/ubi0:<volname>colon syntax — Erlang'sUBootEnvopens the path with:file.open/2and can't parse the colon-name shorthand that the C tools accept.fw_setenvon the device (defaults to/usr/sbin/fw_setenv). Buildroot'sBR2_PACKAGE_UBOOT_TOOLS_FWPRINTENV=yships this.
Installation
def deps do
[
{:nerves_uboot_env_ubi, "~> 0.1"}
]
endIn config/target.exs:
config :nerves_runtime,
kv_backend: {Nerves.Runtime.KVBackend.UBootEnvUBI, []}If your fw_setenv lives somewhere other than /usr/sbin/fw_setenv:
config :nerves_runtime,
kv_backend: {Nerves.Runtime.KVBackend.UBootEnvUBI,
[fw_setenv: "/sbin/fw_setenv"]}Status
Used in production on the OpenWRT One Nerves system. Should work on any Linux board where the U-Boot env is in UBI volumes — OpenWrt-derived MediaTek Filogic boards, Banana Pi BPi-R3, etc.
License
Apache-2.0. See LICENSE.