Skip to content

Operations ​

What to do when UBI returns an error or reports an event, what a power cut leaves behind, and what UBI costs. The contract of every call is in include/ubi/ubi.h.

When an attach fails ​

ubi_device_init() writes nothing, so a failed attach leaves the flash as it was. Format the partition only after -ENODEV: after any other error a UBI device may be on it, and a format would destroy it.

returnsmeansdo
-ENODEVno UBI device: the partition is blank or holds other dataformat it, if that is expected
-EBADMSGUBI metadata failed verification: a different key, damage or tamperingkeep the device; a format destroys its data
-ENOTSUPwritten by a newer release, or with more volumes than CONFIG_UBI_MAX_NR_OF_VOLUMESrun the newer firmware, or raise the limit
-EIOflash or crypto failuretry again; if it persists, check the hardware
-EROFSthe state callback returned UBI_STATE_UNTRUSTEDtreat it as a rollback
-EINVALinvalid configuration, a partition geometry UBI cannot use or that differs from the format, or too many corrupt blockscheck the configuration and the devicetree; see maintenance
-EACCESthe key does not exist or does not allow HKDF-SHA256 derivationfix the key or its policy
-ENOMEMnot enough heapsee Resources
-EBUSYthe handle or the partition is in usedetach the other handle first
-ENOSPCmore than 65534 blocks, or volumes that do not fit the partitionuse fewer, larger blocks

Events ​

Events only report: UBI has already acted when the callback runs.

eventmeansdo
UBI_EVENT_HDR_CORRUPTa header failed its CRC: a write or erase cut short, or bit rotnothing after a power cut; data behind a damaged header is kept, see corrupt_pebs
UBI_EVENT_HDR_TAMPEREDa header failed authentication: modified, or written under another keyexpected after a key change until reclaim has run; otherwise keep the device as evidence
UBI_EVENT_VOLUME_TABLE_CORRUPTa volume table copy could not be usednothing while the other copy works
UBI_EVENT_VOLUME_TABLE_DEGRADEDonly one volume table copy is usable, or the copies differrun UBI_MAINTENANCE_REPAIR soon
UBI_EVENT_LEB_ORPHANEDa block names a volume this device never creatednothing; reclaim erases it
UBI_EVENT_PEB_BADa block was retired: a write or erase failed, or its erase count reached the limitafter a failed write, run UBI_MAINTENANCE_REPAIR; after a failed erase the device is read-only
UBI_EVENT_DATA_CORRUPTthe data of a LEB failed its checksum: a change cut short, or damagenothing if the previous contents were used; otherwise the LEB keeps the data as it reads

Power loss ​

cut shortafter the reboot
ubi_leb_change()the old contents or the new; a LEB with no old contents keeps the part of the new data that was written, reported with UBI_EVENT_DATA_CORRUPT
ubi_leb_write_at()the part of the data that was written; the application finds the end of its data itself
ubi_leb_erase(), or reclaim after an unmapthe last contents or none, never older ones
volume create, resize or removethe old layout or the new
UBI_MAINTENANCE_RELOCATEthe LEB in its old block or in the new one
ubi_device_format()the previous device or the new one

The third row needs CONFIG_UBI_ERASE_INVALIDATES_HEADERS, which is on by default. Without it, an erase cut short can leave a block with valid headers and part of its data. Data with a checksum is then reported with UBI_EVENT_DATA_CORRUPT; appended data is not.

A failed write is different from a power cut: what the device reports right after it is what the next attach finds.

Keeping maintenance up ​

What one step of each operation does is in the contract of ubi_maintenance(). When to run them:

operationwhenbudget
UBI_MAINTENANCE_RECLAIMwhenever the device is idlea few blocks; with a full free pool, writes need no erase
UBI_MAINTENANCE_RELOCATErelocatable_pebs is not zeroone at a time; each step copies a block and erases one
UBI_MAINTENANCE_REPAIRafter UBI_EVENT_VOLUME_TABLE_DEGRADED or UBI_EVENT_PEB_BADuntil remaining is zero
UBI_MAINTENANCE_DISCARDwhen nothing on the corrupt_pebs is needed any moreall of them

Attach refuses a partition once corrupt blocks reach a twentieth of its good blocks, rounded down, or eight when that is zero. Discard them before that.

After a failed erase the device is read-only until the next attach: reads work, and every call that would write returns -EROFS; see Bad blocks. A part that keeps failing erases is at the end of its life.

Changing the key ​

Everything UBI writes is authenticated with keys derived from the keying material, so new keying material means a new device:

  1. Attach under the old key and copy out what has to survive.
  2. Detach and format under the new key.
  3. Attach under the new key. Each old block fails its MAC, is reported with UBI_EVENT_HDR_TAMPERED and counted in reclaimable_pebs.
  4. Run UBI_MAINTENANCE_RECLAIM until reclaimable_pebs is zero.
  5. Create the volumes and write back what was copied out.

The erase counts are authenticated with the old key, so they are lost with it.

Resources ​

Sizes from the nRF5340 build (Cortex-M33, -Os, logging off, mbedTLS), timings on the nRF5340 DK:

whathow much
codeabout 11 KB, plus mbedTLS for AES-CMAC, HKDF and SHA-256
handle, ubi_device_size()328 bytes with 4 volumes, 2248 with 64
heap at attach8 bytes per erase block, and a scratch buffer of 392 bytes with 4 volumes, 3480 with 64
heap during a formata handle and a scratch buffer of its own
stack1704 bytes at most for any call on a Cortex-M33, with the default CONFIG_UBI_IO_CHUNK_SIZE; a larger chunk adds its growth
attach151 ms at most for 64 blocks of 4 KiB on the DK's MX25R64
erase87 ms for a 4 KiB block and 1.2 s for a 64 KiB one on the same part

CONFIG_UBI_SELF_CHECKS adds one bit per erase block of heap.

Limits ​

  • 4 to 65534 erase blocks of one size, each larger than the two headers and the volume table record.
  • A write block that divides 64 bytes.
  • Volume names of 1 to 16 characters.
  • Up to CONFIG_UBI_MAX_NR_OF_VOLUMES volumes, 64 at most. The option may grow from one firmware to the next, never shrink: a build that allows fewer volumes than a device holds refuses it with -ENOTSUP.
  • Erase counts up to 2³¹ − 1.

Released under the MIT License.