GRiSP UBoot Environment Managment Library
grisp_uboot provides an Erlang interface to read and write U‑Boot
environment blocks, similar in spirit to grisp_barebox, but targeting the
U‑Boot environment format. It supports non‑redundant and redundant
environments and discovers locations from an fw_env.config‑formatted file.
grisp_uboot:start_link(Config)– start the server with a prebuiltgrisp_uboot_config:config().grisp_uboot:configuration/0|1– parse a config from/etc/fw_env.config, a given file path, or explicit locations.grisp_uboot:read(Config)– read and decode to a deep map.grisp_uboot:write(DeepMap, Config)– encode and write a deep map.grisp_uboot:load/0– load the environment into memory.grisp_uboot:get(Name)– get a value by key.Namecan be a binary key like<<"foo.bar">>or a list path of atoms or binaries (e.g.[foo, bar]or[<<"foo">>, <<"bar">>]). The reserved atomemptymarks empty segments. If a node has both a value and children, list‑formget/1returns the nested map for that node (withvalueand children) rather than only the value.grisp_uboot:get_all/0– return the in‑memory deep map (see shape below).grisp_uboot:set(Name, Value)– update a value or subtree in memory.grisp_uboot:commit/0– write the in‑memory deep map back to storage.grisp_uboot:stop/0– stop the server (useful for tests).
- On disk: flat key/value pairs with arbitrary dots and empty segments.
- In memory (deep map): user keys are binaries; reserved atoms:
value– a node’s own value when it also has childrenempty– an empty path segment (from trailing or double dots)
- List‑path inputs: atoms are converted to binaries; binaries are accepted
directly; the reserved atom
emptymarks empty segments. - Path conversion examples:
<<"foo..bar">>→[<<"foo">>, empty, <<"bar">>]<<"a.">>→[<<"a">>, empty]
- Flattening preserves exact flat keys (including empty segments). Double dots are written as double dots to ensure byte‑for‑byte round‑trips.
Start from default config file:
{ok, Cfg} = grisp_uboot:configuration(),
{ok, _Pid} = grisp_uboot:start_link(Cfg),
ok = grisp_uboot:load(),
Val = grisp_uboot:get(<<"grisp_unit_id">>).Start from a specific fw_env.config file:
CfgPath = <<"test/data/single_env_mkenvimage.config">>,
{ok, Cfg} = grisp_uboot:configuration(CfgPath),
{ok, _Pid} = grisp_uboot:start_link(Cfg),
ok = grisp_uboot:load(),
% Binary and list‑form access
Path1 = grisp_uboot:get(<<"b.grisp_fw.system.path">>),
Path2 = grisp_uboot:get([b, grisp_fw, system, path]).Start from explicit locations:
Locs = [{<<"/tmp/env.bin">>, 0, 1024}],
{ok, Cfg} = grisp_uboot:configuration(Locs),
{ok, _Pid} = grisp_uboot:start_link(Cfg),
ok = grisp_uboot:load().Set and commit changes:
ok = grisp_uboot:set(<<"foo.bar">>, <<"X">>),
ok = grisp_uboot:set([toto, tata], <<"Y">>),
ok = grisp_uboot:commit().Get the full deep map (binary user keys; value/empty reserved atoms):
All = grisp_uboot:get_all().
% Example shape
% #{ <<"b">> => #{<<"grisp_fw">> => #{<<"system">> => #{<<"path">> => <<"/dev/mmcblk0p7">>}}},
% <<"net">> => #{<<"cfg">> => #{<<"dhcp">> => #{<<"enabled">> => <<"1">>, empty => <<"trailing">>}}},
% <<"a">> => #{empty => #{<<"b">> => <<"doubledot">>}} }.Low‑level helpers are available for power users and tests:
grisp_uboot_serializer:encode/1– map → binary (key=value\0...\0).grisp_uboot_serializer:decode/1– binary → map.grisp_uboot_io:package/3– package contents to an environment block (CRC + optional generation + padding).grisp_uboot_io:unpackage/2– validate and unpack an environment block.grisp_uboot_io:read/1andgrisp_uboot_io:write/2– raw read/write usinggrisp_uboot_config.grisp_uboot_config:from_file/1– parse anfw_env.configfile. Relative device paths are resolved against the config file’s directory.grisp_uboot_config:from_string/1– parse from contents; relative paths resolved against the current working directory.grisp_uboot_config:from_locations/1– build a config from a location list.
This project uses Common Test exclusively. The binary test data under
test/data/*.bin is checked in, so you do not need any external tools to run
the test suite. Only if you change the support inputs under test/data/support/
should you regenerate the binaries with the helper script (requires
mkenvimage, fwup, fw_setenv):
test/data/support/gen_test_data.shRun the tests:
rebar3 ctThe suites cover:
- Configuration parsing (
fw_env.config): single and redundant layouts - Serializer encode/decode round‑trips and edge cases
- Packaging/unpackaging logic (CRC, generation byte, padding)
- I/O read/write behavior (non‑redundant and redundant) using temp files
- End‑to‑end reads using committed binary fixtures
Binary test data is checked in so that no external tools are required to run the test suite.
$ rebar3 compile
See LICENSE.md.