Bootloader storage

The bootloader storage library is used to read and write both one-time programmable (OTP) data and a non-volatile counter.

If the nRF Secure Immutable Bootloader (NSIB) is enabled, it should be the only user of this library. The application image can only include this library when the NSIB is disabled.

The library has the following functions for either reading or writing, or in some cases both reading and writing:

  • The lifecycle state of the device, used to deny certain operations when in wrong lifecycle state.

  • A 32-byte user-defined implementation ID, used to identify the immutable bootloader.

  • Image slot addresses.

  • A monotonic counter, used to enforce anti-rollback protection.

  • Hashes of public keys.

  • Invalidation tokens, used to revoke public keys.

  • Additional public key metadata.

The library uses either the OTP region of the User information configuration registers (UICR), when present on SoCs like the nRF9160 or nRF5340, or the internal flash memory. When the library uses the internal flash memory, the bootloader blocks the write access before booting the next image.

See Provisioning for more information about the provisioned data and how the bootloader uses it.

See tests/subsys/bootloader/bl_storage/ for tests of the library.

API documentation

Header file: include/bl_storage.h
Source files: subsys/bootloader/bl_storage/
group bl_storage




enum lcs

The PSA life cycle states a device can be in.

The LCS can be only transitioned in the order they are defined here.




uint32_t s0_address_read(void)

Function for reading address of slot 0.


Address of slot 0.

uint32_t s1_address_read(void)

Function for reading address of slot 1.


Address of slot 1.

uint32_t num_public_keys_read(void)

Function for reading number of public key data slots.


Number of public key data slots.

int verify_public_keys(void)

Function for reading number of public key data slots.

Return values
  • 0 – if all keys are ok.

  • -EHASHFF – if one or more keys contains an aligned 0xFFFF.

int public_key_data_read(uint32_t key_idx, uint8_t *p_buf)

Function for reading public key hashes.

  • key_idx[in] Index of key.

  • p_buf[out] Pointer to where the hash will be written. The buffer must be at least SB_PUBLIC_KEY_HASH_LEN bytes large.

Return values
  • -EINVAL – Key has been invalidated.

  • -EFAULT – key_idx is too large. There is no key with that index.


Number of successfully written bytes to p_buf.

void invalidate_public_key(uint32_t key_idx)

Function for invalidating a public key.

The public key will no longer be returned by public_key_data_read.

  • key_idx[in] Index of key.

uint16_t num_monotonic_counter_slots(void)

Get the number of monotonic counter slots.


The number of slots. If the provision page does not contain the information, 0 is returned.

uint16_t get_monotonic_counter(void)

Get the current HW monotonic counter.


The current value of the counter.

int set_monotonic_counter(uint16_t new_counter)

Set the current HW monotonic counter.


FYI for users looking at the values directly in flash: Values are stored with their bits flipped. This is to squeeze one more value out of the counter.

  • new_counter[in] The new counter value. Must be larger than the current value.

Return values
  • 0 – The counter was updated successfully.

  • -EINVALnew_counter is invalid (must be larger than current counter, and cannot be 0xFFFF).

  • -ENOMEM – There are no more free counter slots (see CONFIG_SB_NUM_VER_COUNTER_SLOTS ).

void otp_copy32(uint8_t *restrict dst, uint32_t volatile *restrict src, size_t size)

Copies src into dst. Reads from src are done 32 bits at a time. Writes to dst are done a byte at a time.

  • dst[out] destination buffer.

  • src[in] source buffer. Must be 4-byte-aligned.

  • size[in] number of bytes in src to copy into dst. Must be divisible by 4.

void read_implementation_id_from_otp(uint8_t *buf)

Read the implementation id from OTP and copy it into a given buffer.

  • buf[out] Buffer that has at least BL_STORAGE_IMPLEMENTATION_ID_SIZE bytes

int read_life_cycle_state(enum lcs *lcs)

Read the current life cycle state the device is in from OTP,.

  • lcs[out] Will be set to the current LCS the device is in

Return values
  • 0 – The LCS read was successful.

  • -EREADLCS – Error on reading from OTP or invalid OTP content.

int update_life_cycle_state(enum lcs next_lcs)

Update the life cycle state in OTP.

  • next_lcs[in] Must be the same or the successor state of the current one.

Return values
  • 0 – Success.

  • -EREADLCS – Reading the current state failed.

  • -EINVALIDLCS – Invalid next state.