A Nerves.Runtime.KVBackend for U-Boot environments stored in UBI volumes.
Why this exists
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 :file and the default
Nerves.Runtime.KVBackend.UBootEnv) returns EPERM. The standard
Nerves backend therefore can't write the env on UBI-backed boards;
Nerves.Runtime.validate_firmware/0 and the whole
Nerves.Runtime.StartupGuard chain fall over with {:error, :eperm}.
This backend works around the gap by:
- Reading through the Erlang
UBootEnvlibrary (which uses plainpread/3— that works fine on/dev/ubi*character devices). - Writing by shelling out to the C
fw_setenvtool fromu-boot-tools, which issues theUBI_IOCVOLUPioctl transparently for/dev/ubi*paths.
Requirements on the target system
/etc/fw_env.configpointing at the UBI volumes that hold the env (one or two volumes for redundancy).fw_setenvavailable somewhere on the device. Defaults to/usr/sbin/fw_setenv; override with the:fw_setenvoption.
Usage
Add to your firmware app's deps:
{:nerves_uboot_env_ubi, "~> 0.1"}Wire it up in config/target.exs:
config :nerves_runtime,
kv_backend: {Nerves.Runtime.KVBackend.UBootEnvUBI, []}Or with options:
config :nerves_runtime,
kv_backend: {Nerves.Runtime.KVBackend.UBootEnvUBI,
[fw_setenv: "/sbin/fw_setenv"]}Options
:fw_setenv— path to thefw_setenvbinary. Defaults to"/usr/sbin/fw_setenv".