DEV Community

Ripan Deuri
Ripan Deuri

Posted on

MCUboot: Understanding the Image Trailer and How It Tracks Firmware Update Progress

The MCUboot bootloader ensures fail-safe firmware updates on embedded devices by closely tracking the progress of image swaps inside a reserved flash area called the image trailer. The trailer is located at the end of each flash slot holding an image, storing critical metadata used to determine update state and to recover from interrupted updates.

Image Trailer Format

An image trailer has the following structure:

    +---------------------------------------------------------------+
    |0                   1                   2                   3  |
    |0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1|
    +---------------------------------------------------------------+
    ~                                                               ~
    ~    Swap status (BOOT_MAX_IMG_SECTORS * min-write-size * 3)    ~
    ~                                                               ~
    +---------------------------------------------------------------+
    |                 Encryption key 0 (16 octets) [*]              |
    |                                                               |
    +---------------------------------------------------------------+
    |                    0xff padding as needed                     |
    |  (BOOT_MAX_ALIGN minus 16 octets from Encryption key 0) [*]   |
    +---------------------------------------------------------------+
    |                 Encryption key 1 (16 octets) [*]              |
    |                                                               |
    +---------------------------------------------------------------+
    |                    0xff padding as needed                     |
    |  (BOOT_MAX_ALIGN minus 16 octets from Encryption key 1) [*]   |
    +---------------------------------------------------------------+
    |                      Swap size (4 octets)                     |
    +---------------------------------------------------------------+
    |                    0xff padding as needed                     |
    |        (BOOT_MAX_ALIGN minus 4 octets from Swap size)         |
    +---------------------------------------------------------------+
    |   Swap info   |  0xff padding (BOOT_MAX_ALIGN minus 1 octet)  |
    +---------------------------------------------------------------+
    |   Copy done   |  0xff padding (BOOT_MAX_ALIGN minus 1 octet)  |
    +---------------------------------------------------------------+
    |   Image OK    |  0xff padding (BOOT_MAX_ALIGN minus 1 octet)  |
    +---------------------------------------------------------------+
    |                    0xff padding as needed                     |
    |         (BOOT_MAX_ALIGN minus 16 octets from MAGIC)           |
    +---------------------------------------------------------------+
    |                       MAGIC (16 octets)                       |
    |                                                               |
    +---------------------------------------------------------------+
Enter fullscreen mode Exit fullscreen mode

[*]: Only present if the encryption option is enabled (MCUBOOT_ENC_IMAGES).

Image Trailer layout for encryption disabled, BOOT_MAX_IMG_SECTORS=8, min-write-size=1, BOOT_MAX_ALIGN=4:

+-------------+---------------+----------------------------------+
| Offset      | Size (Byte)   | Field                            |
+-------------+---------------+----------------------------------+
| -56         | 24            | Swap Status (8 sectors × 3 bytes)|
| -32         | 4             | Swap Size (4 bytes)              |
| -28         | 4             | Swap Info (1 byte + pad)         |
| -24         | 4             | Copy Done (1 byte + pad)         |
| -20         | 4             | Image OK (1 byte + pad)          |
| -16         | 16            | Magic                            |
+-------------+---------------+----------------------------------+
Enter fullscreen mode Exit fullscreen mode

Image Trailer Fields

The key image trailer fields are -

  • Magic: A unique 16-byte identifier 0x77c2b96d 0x23d84f67 validating the presence and format of the image trailer. The size of Magic varies based on BOOT_MAX_ALIGN. Hex bytes in flash: 6D B9 C2 77 67 4F D8 23.
  • Image Ok: A byte indicating the newly booted image is confirmed good (0x01: confirmed, 0xFF: not confirmed). If not confirmed, MCUboot may rollback.
  • Copy Done: A byte indicating if the image copy (swap) operation in this slot has completed successfully (0x01: done, 0xFF: not done).
  • Swap Info: A byte which encodes following information:
    • Swap type (bits 0-3): It indicates the type of swap operation
    • 1: None (attempts to boot from slot 0)
    • 2: Test (swap to slot 1)
    • 3: Permanent (swap to slot 1 and permanent switch)
    • 4: Revert (swap back to previous slot)
    • 5: Swap failed
    • Image number (bits 4-7): It indicates the image number in case of multi image boot. 0 for single image boot.
  • Swap Size: This field (4 bytes) stores the total number of bytes that must be swapped between the primary and secondary image slots during an update. It ensures that the bootloader swaps only the valid portion of the image region, not the whole slot.
  • Swap Status: Records the progress of the ongoing image swap on a per-sector basis.

How Swap Status Works

Each sector involved in the swap is represented by three bytes in the Swap Status field. These bytes change from their erased state (0xFF) step-by-step as the swap progresses:

+----------+-------+----------------------+
| Record # | Value | Description          |
+----------+-------+----------------------+
| rec0     | 0xFF  | unswapped            |
| rec1     | 0xFF  | (erased flash state) |
| rec2     | 0xFF  |                      |
+----------+-------+----------------------+
| rec0     | 0x01  | Swap stage 1         |
| rec1     | 0xFF  |                      |
| rec2     | 0xFF  |                      |
+----------+-------+----------------------+
| rec0     | 0x01  | Swap stage 2         |
| rec1     | 0x02  |                      |
| rec2     | 0xFF  |                      |
+----------+-------+----------------------+
| rec0     | 0x01  | Swap stage 3         |
| rec1     | 0x02  |                      |
| rec2     | 0x03  |                      |
+----------+-------+----------------------+
Enter fullscreen mode Exit fullscreen mode

The three swap stages correspond roughly to phases in the swap process per sector, for example:

  • Stage 1: Copy sector data from primary slot to scratch area
  • Stage 2: Copy sector data from secondary slot to primary slot
  • Stage 3: Copy sector data from scratch area to secondary slot

How MCUboot Determines Swap Type

MCUboot uses several key fields from both the primary and secondary image slots to decide the "swap type," which dictates how it handles firmware updates. This decision happens at boot based on the current state of the image trailers in flash.

  • Magic: A signature indicating a valid image.
  • image-ok: Indicates if the image has been confirmed as "good" after a successful boot.
  • copy-done: Shows whether the secondary image has been fully copied to the primary slot.

Five main states arise from combinations of these fields, with these outcomes:

  • State 1: Revert Swap: The secondary slot has a valid image (magic = good) not yet confirmed (image-ok unset), but a copy was done (copy-done set). MCUboot decides to revert, restoring the previous image.
+-------------+---------------+----------------+
| State       | Primary Slot  | Secondary Slot |
+-------------+---------------+----------------+
| State 1     | Any           | Magic: Good    |
|             | Any           | image-ok: Unset|
|             | Any           | copy-done: Set |
+-------------+---------------+----------------+
| Result: Revert                               |
+----------------------------------------------+
Enter fullscreen mode Exit fullscreen mode
  • State 2: Test Swap: Secondary slot valid but image-ok unset, copy-done may be set or unset. MCUboot swaps images temporarily to test the new image, allowing rollback if the new firmware fails.
+-------------+---------------+----------------+
| State       | Primary Slot  | Secondary Slot |
+-------------+---------------+----------------+
| State 2     | Any           | Magic: Good    |
|             | Any           | image-ok: Unset|
|             | Any           | copy-done: Any |
+-------------+---------------+----------------+
| Result: Test                                 |
+----------------------------------------------+
Enter fullscreen mode Exit fullscreen mode
  • State 3: Permanent Swap: Secondary slot valid and confirmed (image-ok = 0x01). MCUboot commits the swap permanently, running the new image permanently.
+-------------+---------------+----------------+
| State       | Primary Slot  | Secondary Slot |
+-------------+---------------+----------------+
| State 3     | Any           | Magic: Good    |
|             | Any           | image-ok: 0x01 |
|             | Any           | copy-done: Any |
+-------------+---------------+----------------+
| Result: Permanent                            |
+----------------------------------------------+
Enter fullscreen mode Exit fullscreen mode
  • State 4: Revert from Primary: Primary slot marked as valid (magic good), but image-ok unset and copy-done set. This also signals a revert to previous firmware.
+-------------+---------------+----------------+
| State       | Primary Slot  | Secondary Slot |
+-------------+---------------+----------------+
| State 4     | Magic: Good   | Any            |
|             | image-ok:0xFF | Any            |
|             | copy-done:0x01| Any            |
+-------------+---------------+----------------+
| Result: Revert                               |
+-------------+---------------+----------------+
Enter fullscreen mode Exit fullscreen mode
  • State 5: MCUboot will attempt to boot the contents of the primary slot directly, and the result is "None". If the image in the primary slot is not valid, the result is "Fail". If a fatal error occurs during boot, the result is "Panic". MCUboot hangs if the result is either "Fail" or "Panic".
+-------------+---------------+----------------+
| State       | Primary Slot  | Secondary Slot |
+-------------+---------------+----------------+
| State 5     | Any           | Magic: Any     |
|             | Any           | image-ok: Any  |
|             | Any           | copy-done: Any |
+-------------+---------------+----------------+
| Result: None/Fail/Panic                      |
+----------------------------------------------+
Enter fullscreen mode Exit fullscreen mode

References:

https://docs.nordicsemi.com/bundle/ncs-latest/page/mcuboot/design.html
https://docs.mcuboot.com/design.html

Top comments (0)