Skip to content

grisp/grisp_uboot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

grisp_uboot

GRiSP UBoot Environment Managment Library

Overview

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.

Public API

  • grisp_uboot:start_link(Config) – start the server with a prebuilt grisp_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. Name can be a binary key like <<"foo.bar">> or a list path of atoms or binaries (e.g. [foo, bar] or [<<"foo">>, <<"bar">>]). The reserved atom empty marks empty segments. If a node has both a value and children, list‑form get/1 returns the nested map for that node (with value and 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).

Data model and key conventions

  • 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 children
    • empty – an empty path segment (from trailing or double dots)
  • List‑path inputs: atoms are converted to binaries; binaries are accepted directly; the reserved atom empty marks 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.

Examples

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">>}} }.

Advanced (IO/Serializer/Config)

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/1 and grisp_uboot_io:write/2 – raw read/write using grisp_uboot_config.
  • grisp_uboot_config:from_file/1 – parse an fw_env.config file. 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.

Testing

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.sh

Run the tests:

rebar3 ct

The 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.

Build

$ rebar3 compile

License

See LICENSE.md.

About

GRiSP UBoot Environment Managment Library

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published