Configuration

What this page covers: All Kconfig options, DeviceTree partition setup, and sizing guidelines for UBI.

Prerequisites: Overview and Getting Started.

UBI is configured via Zephyr’s Kconfig system and DeviceTree overlays.

Kconfig Options

Enable UBI and its options in your prj.conf:

CONFIG_UBI_ENABLE=y

Option Reference

Option

Type

Default

Range

Description

CONFIG_UBI_ENABLE

bool

n

Enable the UBI subsystem

CONFIG_UBI_MEM_BACKEND_STATIC

bool

y

Use k_mem_slab pools for all UBI allocations (default)

CONFIG_UBI_MEM_BACKEND_HEAP

bool

n

Use k_malloc/k_free for all UBI allocations (legacy)

CONFIG_UBI_MAX_NR_OF_DEVICES

int

1

1–4

Maximum number of concurrent UBI device handles (static backend)

CONFIG_UBI_MAX_NR_OF_DATA_PEBS

int

14

1–4096

Maximum data PEBs per device (static backend pool sizing)

CONFIG_UBI_MEM_STATS

bool

n

Enable slab pool usage statistics (static backend only)

CONFIG_UBI_DEV_HDR_NR_OF_RES_PEBS

int

2

2–4

Number of reserved PEBs for device/volume metadata

CONFIG_UBI_MAX_NR_OF_VOLUMES

int

10

1–128

Maximum number of volumes per device

CONFIG_UBI_PEB_WRITE_RETRY_COUNT

int

3

1–5

Flash write retries on data PEBs before marking bad

CONFIG_UBI_BAD_PEB_TORTURE_CYCLES

int

3

1–10

Bad PEBs tortured per erase_peb() call

CONFIG_UBI_BAD_PEB_TORTURE_MAX_PER_ERASE

int

1

1–10

Max erase attempts per bad PEB during torture

CONFIG_UBI_LOG_LEVEL_*

choice

INF

Log verbosity: OFF, ERR, WRN, INF, DBG

CONFIG_UBI_TEST_API_ENABLE

bool

n

Enable test-only APIs (ubi_device_get_peb_ec, ubi_device_check_invariants)

CONFIG_UBI_TEST_FAULT_INJECTION

bool

n

Controllable allocation failure hook for simulating OOM. Depends on CONFIG_UBI_TEST_API_ENABLE.

CONFIG_UBI_CRYPTO

bool

n

Enable the secure (authenticated-encryption) backend. Requires Mbed TLS PSA Crypto.

CONFIG_UBI_CRYPTO_MAX_KEY_VERSIONS

int

4

1–255

Maximum distinct key versions per attach session. Sizes per-key-version bookkeeping arrays.

CONFIG_UBI_CRYPTO_MAX_ALLOWLIST_LEN

int

4

1–255

Maximum entries in ubi_crypto_policy.allowed_key_versions.

CONFIG_UBI_CRYPTO_METADATA_COUNTER_BUDGET

int

1000000

Max metadata AEAD invocations per {domain, key_version} before KEY_ROTATE event.

CONFIG_UBI_CRYPTO_METADATA_TOTAL_AUTH_BYTES_BUDGET

int

100000000

Max cumulative authenticated metadata bytes per {domain, key_version}.

CONFIG_UBI_CRYPTO_LEB_WRITE_BUDGET

int

1000000

Max LEB AEAD invocations per {key_version, volume_id}.

CONFIG_UBI_CRYPTO_LEB_TOTAL_AUTH_BYTES_BUDGET

int

100000000

Max cumulative authenticated LEB bytes per {key_version, volume_id}.

CONFIG_UBI_CRYPTO_ROTATE_SOON_PCT

int

80

1–99

Soft rotation threshold (%). Emits KEY_ROTATE_SOON.

CONFIG_UBI_CRYPTO_ROTATE_NOW_PCT

int

95

1–100

Hard rotation threshold (%). Emits KEY_ROTATE_NOW; writes may be rejected.

CONFIG_UBI_CRYPTO_LEB_CHUNKED

bool

n

Use chunked LEB layout: multiple AEAD tags per LEB for partial-read authentication (§7.8).

CONFIG_UBI_CRYPTO_LEB_CHUNK_SIZE

int

4096

256–65536

Chunk size in bytes (must be multiple of flash write alignment). Smaller = finer reads, more tag overhead.

CONFIG_UBI_CRYPTO_PEB_CACHE

bool

y

Allocate a PEB-sized staging buffer for secure encrypt/decrypt. Required for secure I/O.

CONFIG_UBI_CRYPTO_PEB_CACHE_STATIC

bool

n

Allocate PEB staging buffer at compile time (else per-device at init).

CONFIG_UBI_CRYPTO_FRESHNESS_SYNC_DELTA

int

0

0–65535

Mutations between sync_freshness callbacks. 0 = sync after every commit.

CONFIG_UBI_CRYPTO_STRICT_RO_ON_RNG_FAILURE

bool

y

Enter read-only mode on RNG failure instead of only rejecting the current write.

CONFIG_UBI_CRYPTO_STRICT_RO_ON_POLICY_FAILURE

bool

y

Enter read-only on freshness policy rejection or rollback mismatch.

CONFIG_UBI_CRYPTO_STRICT_RO_ON_FRESHNESS_SYNC_FAILURE

bool

n

Enter read-only when sync_freshness callback errors.

CONFIG_UBI_CRYPTO_TEST_FAULT_INJECTION

bool

n

Secure backend fault injection (PSA crypto failures). Depends on UBI_TEST_FAULT_INJECTION.

Memory Backend

UBI supports two memory backends, selected at compile time via a Kconfig choice:

  • Static (CONFIG_UBI_MEM_BACKEND_STATIC, default): All allocations use k_mem_slab pools sized at compile time. Provides deterministic RAM budget and full isolation from the application heap. Pool sizes are derived from CONFIG_UBI_MAX_NR_OF_DEVICES, CONFIG_UBI_MAX_NR_OF_DATA_PEBS, and CONFIG_UBI_MAX_NR_OF_VOLUMES.

  • Heap (CONFIG_UBI_MEM_BACKEND_HEAP): Delegates to k_malloc/k_free (legacy behaviour). Useful for prototyping or when pool sizing is unknown.

When to use each:

Use case

Recommended backend

Production deployment

STATIC — deterministic, no fragmentation

Prototyping / unknown flash geometry

HEAP — no pool sizing required

Multiple UBI devices

STATIC — set CONFIG_UBI_MAX_NR_OF_DEVICES

Memory Sizing Guide

Under the static backend, all pool memory is pre-allocated at compile time. The total RAM budget is:

Pool

Formula

Example (D=14, V=2)

Device slab

MAX_NR_OF_DEVICES × sizeof(ubi_device)

1 × 136 = 136 B

Volume slab

MAX_NR_OF_DEVICES × MAX_NR_OF_VOLUMES × sizeof(ubi_volume)

1 × 10 × 44 = 440 B

Leaf slab

MAX_NR_OF_DEVICES × (MAX_NR_OF_DATA_PEBS + MAX_NR_OF_VOLUMES) × 16

1 × (14+10) × 16 = 384 B

Scratch slab

MAX(DEV_HDR + MAX_VOL × VOL_HDR, 2 × CHUNK_SIZE + 16) (1 block)

32 + 10 × 48 = 512 B (or 2×4096+16 = 8208 B with chunked)

Total

~1,464 B

At init time, ubi_device_init() verifies that the actual flash geometry fits within the configured pools. If the flash partition has more data PEBs than CONFIG_UBI_MAX_NR_OF_DATA_PEBS, init returns -ENOMEM.

Impact Analysis

Option

Flash layout

RAM usage

Recovery / robustness

Performance

MEM_BACKEND_STATIC

No impact

Pre-allocated pools (known at compile time)

No fragmentation risk

O(1) slab alloc

MEM_BACKEND_HEAP

No impact

Dynamic; proportional to PEBs + volumes

Subject to heap fragmentation

k_malloc overhead

MAX_NR_OF_DEVICES

No impact

Multiplies all pool sizes

No impact

No impact

MAX_NR_OF_DATA_PEBS

No impact

16 B per PEB in leaf slab

Init fails if flash has more data PEBs

No impact

NR_OF_RES_PEBS

More reserved PEBs = fewer data PEBs

+16 B per additional reserved PEB (RBT node)

Higher = more redundancy for metadata; 3–4 adds cold spares

No measurable impact

MAX_NR_OF_VOLUMES

Limits volume headers stored in reserved PEBs

+48 B per volume + 16 B per volume RBT node

No direct impact

No measurable impact

PEB_WRITE_RETRY_COUNT

No impact

No impact

Higher = more chances to recover from transient write errors

Higher = slower failure path (more retries)

BAD_PEB_TORTURE_CYCLES

No impact

No impact

Higher = more aggressive bad block recovery attempts

Higher = longer erase_peb() calls

BAD_PEB_TORTURE_MAX_PER_ERASE

No impact

No impact

Higher = more erase attempts per bad PEB

Higher = longer per-PEB torture

Log Level

UBI uses Zephyr’s logging subsystem. Set the log level in prj.conf:

# Show only errors
CONFIG_UBI_LOG_LEVEL_ERR=y

# Debug everything
CONFIG_UBI_LOG_LEVEL_DBG=y

Flash Partition (DeviceTree)

UBI requires a named flash partition defined in a DeviceTree overlay. The partition label is referenced at compile time via FIXED_PARTITION_ID() and FIXED_PARTITION_DEVICE().

native_sim (simulator)

&flash0 {
    erase-block-size = <8192>;

    partitions {
        compatible = "fixed-partitions";
        #address-cells = <1>;
        #size-cells = <1>;

        ubi_partition: partition@0 {
            label = "ubi_partition";
            reg = <0x00000000 DT_SIZE_K(128)>;
        };
    };
};

b_u585i_iot02a (STM32U5)

&flash0 {
    partitions {
        compatible = "fixed-partitions";
        #address-cells = <1>;
        #size-cells = <1>;

        ubi_partition: partition@d0000 {
            label = "ubi_partition";
            reg = <0x000d0000 DT_SIZE_K(128)>;
        };
    };
};

nrf5340dk/nrf5340/cpuapp (nRF5340 DK)

&flash0 {
    partitions {
        compatible = "fixed-partitions";
        #address-cells = <1>;
        #size-cells = <1>;

        ubi_partition: partition@f0000 {
            label = "ubi_partition";
            reg = <0x000f0000 DT_SIZE_K(64)>;
        };
    };
};

nRF5340 has 4 KB erase blocks (vs 8 KB on STM32U5). With 64 KB the partition yields 16 PEBs (2 reserved, 14 data), matching the default CONFIG_UBI_MAX_NR_OF_DATA_PEBS.

Sizing Guidelines

  • Minimum: At least N + 2 PEBs (N reserved + 2 data), where N = CONFIG_UBI_DEV_HDR_NR_OF_RES_PEBS. In practice, use >= 8 PEBs.

  • Reserved PEBs: The first N PEBs are reserved for device/volume metadata (configurable via CONFIG_UBI_DEV_HDR_NR_OF_RES_PEBS, default 2). Only PEBs N..total-1 are available for volume data.

  • LEB size: erase_block_size - 48 bytes (48 bytes are consumed by EC + VID headers on each data PEB).

  • Example (STM32U5): With 8 KB erase blocks and 128 KB partition: 16 total PEBs, 2 reserved, 14 data PEBs, each with 8144 B usable per LEB.

  • Example (nRF5340): With 4 KB erase blocks and 64 KB partition: 16 total PEBs, 2 reserved, 14 data PEBs, each with 4048 B usable per LEB.

Zephyr Module Integration

UBI registers as a Zephyr module via zephyr/module.yml. When using west, add UBI as a project in your west.yml:

manifest:
  projects:
    - name: ubi
      url: https://github.com/kamil-kielbasa/ubi
      revision: main
      path: module/lib/ubi

Then initialize and update:

west init -l .
west update --narrow -o=--depth=1