Bootloader storage

The bootloader storage library is used by the Immutable bootloader to read from and write to a protected data area that contains the provisioned bootloader data. The library can also be included into the application to allow reading the provisioned data.

The provisioned data is stored in the one-time programmable (OTP) region of UICR, if available (for example, on nRF9160 and the nRF5340 application core). In this case, it can only be read from applications that are in the secure domain. If OTP is not available, the data is stored in a regular flash page, and the bootloader blocks write access to it before booting the next image. In this case, some functions do not work when they are called from the application.

The library stores the following data:

  • Image slot sizes

  • Hashes of public keys

  • Invalidation tokens used to revoke public keys

  • Application versions

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

You can find tests for the library at tests/subsys/bootloader/bl_storage/.

Storing version information

The bootloader storage can be used to keep track of the version of the application. When updating the application, the Bootloader firmware validation library checks if the new version is newer than the current version and only accepts the new image if it is. After updating, the application must then store the new version information in the bootloader storage.

This functionality is implemented as a monotonic version counter that contains a series of 16-bit integer values. Each update to the counter is written to the next available slot. When reading the counter, the bootloader storage library iterates over each slot and returns the largest value.

The number of available slots, thus the number of different version numbers that can be stored, is configurable through CONFIG_SB_NUM_VER_COUNTER_SLOTS.

The monotonic counter is enabled by default. You can disable it through CONFIG_SB_MONOTONIC_COUNTER. If the counter is enabled, the Bootloader firmware validation library checks it against an image’s version during bl_validate_firmware().

API documentation

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

Functions

uint32_t s0_address_read(void)

Function for reading address of slot 0.

Return

Address of slot 0.

uint32_t s1_address_read(void)

Function for reading address of slot 1.

Return

Address of slot 1.

uint32_t num_public_keys_read(void)

Function for reading number of public key data slots.

Return

Number of public key data slots.

int verify_public_keys(void)

Function for reading number of public key data slots.

Return Value
  • 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, size_t buf_size)

Function for reading public key data.

Return

Number of bytes written to p_buf is successful.

Parameters
  • [in] key_idx: Index of key.

  • [out] p_buf: Pointer to area where key data will be stored.

  • [in] buf_size: Size of buffer, in bytes, provided in p_buf.

Return Value
  • -EINVAL: Key has been invalidated.

  • -ENOMEM: The provided buffer is too small.

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

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.

Parameters
  • [in] key_idx: Index of key.

uint16_t num_monotonic_counter_slots(void)

Get the number of monotonic counter slots.

Return

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.

Return

The current value of the counter.

int set_monotonic_counter(uint16_t new_counter)

Set the current HW monotonic counter.

Note

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.

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

Return Value
  • 0: The counter was updated successfully.

  • -EINVAL: new_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 ).