LoginSignup
1
0

More than 3 years have passed since last update.

Design document of mcuboot

Last updated at Posted at 2020-11-03

Zephyr OS等で使われているmcubootの仕組みを理解する目的で、mcubootのdesign documentを一部和訳しました。機械翻訳を多用してます。
あまりに長いのでまだすべての和訳は行えていません。徐々に対応予定…

オリジナルはこちら。
https://mcuboot.com/mcuboot/design.html

Summary

mcuboot comprises two packages:
mcubootは二つのパッケージで構成される。

  • The bootutil library (boot/bootutil)
  • The boot application (each port has its own at boot/)

The bootutil library performs most of the functions of a boot loader. In particular, the piece that is missing is the final step of actually jumping to the main image. This last step is instead implemented by the boot application. Boot loader functionality is separated in this manner to enable unit testing of the boot loader. A library can be unit tested, but an application can't. Therefore, functionality is delegated to the bootutil library when possible.
bootutil libraryがブートローダのほとんどの機能を実行する。具体的にはメインイメージにジャンプする最後のステップがない。この最後のステップはboot applicationが行う。ブートローダの機能をこのように分離することで、ブートローダのユニットテストが可能となる。libraryに対してはユニットテストができるが、applicationはそれができない。したがって、機能は可能な限りbootutil libraryで実装する。

Limitations

The boot loader currently only supports images with the following characteristics:
ブートローダは現在、以下の特徴を持つイメージのみをサポートする。

  • Built to run from flash.
    フラッシュから起動されるもの。

  • Built to run from a fixed location (i.e., not position-independent).
    所定の場所から起動されるもの(場所非依存ではない)。

Image Format

The following definitions describe the image format.
以下がイメージフォーマットの定義である。

#define IMAGE_MAGIC                 0x96f3b83d

#define IMAGE_HEADER_SIZE           32

struct image_version {
    uint8_t iv_major;
    uint8_t iv_minor;
    uint16_t iv_revision;
    uint32_t iv_build_num;
};

/** Image header.  All fields are in little endian byte order. */
struct image_header {
    uint32_t ih_magic;
    uint32_t ih_load_addr;
    uint16_t ih_hdr_size;           /* Size of image header (bytes). */
    uint16_t ih_protect_tlv_size;   /* Size of protected TLV area (bytes). */
    uint32_t ih_img_size;           /* Does not include header. */
    uint32_t ih_flags;              /* IMAGE_F_[...]. */
    struct image_version ih_ver;
    uint32_t _pad1;
};

#define IMAGE_TLV_INFO_MAGIC        0x6907
#define IMAGE_TLV_PROT_INFO_MAGIC   0x6908

/** Image TLV header.  All fields in little endian. */
struct image_tlv_info {
    uint16_t it_magic;
    uint16_t it_tlv_tot;  /* size of TLV area (including tlv_info header) */
};

/** Image trailer TLV format. All fields in little endian. */
struct image_tlv {
    uint8_t  it_type;   /* IMAGE_TLV_[...]. */
    uint8_t  _pad;
    uint16_t it_len;    /* Data length (not including TLV header). */
};

/*
 * Image header flags.
 */
#define IMAGE_F_PIC                      0x00000001 /* Not supported. */
#define IMAGE_F_NON_BOOTABLE             0x00000010 /* Split image app. */
#define IMAGE_F_RAM_LOAD                 0x00000020

/*
 * Image trailer TLV types.
 */
#define IMAGE_TLV_KEYHASH           0x01   /* hash of the public key */
#define IMAGE_TLV_SHA256            0x10   /* SHA256 of image hdr and body */
#define IMAGE_TLV_RSA2048_PSS       0x20   /* RSA2048 of hash output */
#define IMAGE_TLV_ECDSA224          0x21   /* ECDSA of hash output */
#define IMAGE_TLV_ECDSA256          0x22   /* ECDSA of hash output */
#define IMAGE_TLV_RSA3072_PSS       0x23   /* RSA3072 of hash output */
#define IMAGE_TLV_ED25519           0x24   /* ED25519 of hash output */
#define IMAGE_TLV_ENC_RSA2048       0x30   /* Key encrypted with RSA-OAEP-2048 */
#define IMAGE_TLV_ENC_KW128         0x31   /* Key encrypted with AES-KW-128 */
#define IMAGE_TLV_ENC_EC256         0x32   /* Key encrypted with ECIES-P256 */
#define IMAGE_TLV_ENC_X25519        0x33   /* Key encrypted with ECIES-X25519 */
#define IMAGE_TLV_DEPENDENCY        0x40   /* Image depends on other image */
#define IMAGE_TLV_SEC_CNT           0x50   /* security counter */

Optional type-length-value records (TLVs) containing image metadata are placed after the end of the image.
イメージのメタデータを含むtype-length-valueレコード(TLV)は、イメージの末尾に配置される。

The ih_protect_tlv_size field indicates the length of the protected TLV area. If protected TLVs are present then a TLV info header with magic equal to IMAGE_TLV_PROT_INFO_MAGIC must be present and the protected TLVs (plus the info header itself) have to be included in the hash calculation. Otherwise the hash is only calculated over the image header and the image itself. In this case the value of the ih_protect_tlv_size field is 0.
ih_protect_tlv_size フィールドは保護されたTLV領域の長さを示す。保護されたTLVが存在する場合、IMAGE_TLV_PROT_INFO_MAGICと等しいマジックを持つTLV情報ヘッダが存在しなければならず、保護されたTLV(と情報ヘッダ自体)はハッシュ計算に含まれなければならない。そうでなければ、ハッシュはイメージヘッダとイメージ自身に対してのみ計算される。この場合、ih_protect_tlv_size フィールドの値は0となる。

The ih_hdr_size field indicates the length of the header, and therefore the offset of the image itself. This field provides for backwards compatibility in case of changes to the format of the image header.
ih_hdr_size フィールドはヘッダの長さ、つまりイメージ自体のオフセットを示す。 このフィールドは、イメージヘッダのフォーマットが変更された場合の後方互換性を提供する。

Flash Map

A device's flash is partitioned according to its flash map. At a high level, the flash map maps numeric IDs to flash areas. A flash area is a region of disk with the following properties:
デバイスのフラッシュは、flash mapに従って分割される。 高レベルでは、フラッシュマップは数値IDをflash areasにマッピングする。 flash areasは、以下のプロパティを持つディスクの領域である。

  1. An area can be fully erased without affecting any other areas.
    他の領域に影響を与えることなく、ある領域を完全に消去することができる。

  2. A write to one area does not restrict writes to other areas.

The boot loader uses the following flash area IDs:
ある領域への書き込みは、他の領域への書き込みを制限するものではない。

/* Independent from multiple image boot */
#define FLASH_AREA_BOOTLOADER         0
#define FLASH_AREA_IMAGE_SCRATCH      3
/* If the boot loader is working with the first image */
#define FLASH_AREA_IMAGE_PRIMARY      1
#define FLASH_AREA_IMAGE_SECONDARY    2
/* If the boot loader is working with the second image */
#define FLASH_AREA_IMAGE_PRIMARY      5
#define FLASH_AREA_IMAGE_SECONDARY    6

The bootloader area contains the bootloader image itself. The other areas are described in subsequent sections. The flash could contain multiple executable images therefore the flash area IDs of primary and secondary areas are mapped based on the number of the active image (on which the bootloader is currently working).
ブートローダ領域には、ブートローダイメージ自体が格納される。その他の領域については後述する。フラッシュには複数の実行イメージが含まれている可能性があるため、primary ariaとsecondary areaのフラッシュエリア ID は、(ブートローダが現在動作している) アクティブなイメージの番号に基づいてマッピングされる。

Image Slots

A portion of the flash memory can be partitioned into multiple image areas, each contains two image slots: a primary slot and a secondary slot. Normally, the boot loader will only run an image from the primary slot, so images must be built such that they can run from that fixed location in flash (the exception to this is the direct-xip and the ram-load upgrade mode). If the boot loader needs to run the image resident in the secondary slot, it must copy its contents into the primary slot before doing so, either by swapping the two images or by overwriting the contents of the primary slot. The bootloader supports either swap- or overwrite-based image upgrades, but must be configured at build time to choose one of these two strategies.
フラッシュメモリの一部を複数のイメージ領域に分割することができ、それぞれにprimary slotとsecondary slotの 2 つのイメージスロットがある。通常、ブートローダはprimary slotからイメージを実行するだけなので、イメージはフラッシュ内の所定の場所から実行できるように構築しなければならない (例外は direct-xipram-load アップグレードモード)。ブートローダがsecondary slotに常駐しているイメージを実行する必要がある場合、その前に、2つのイメージを交換するか、primary slotの内容を上書きするかして、その内容をprimary slotにコピーしなければならない。ブートローダは、イメージアップグレードについて交換および上書きの二種類をサポートしているが、 ビルド時にこれら2つのどちらかを選択して設定しなければならない。

In addition to the slots of image areas, the boot loader requires a scratch area to allow for reliable image swapping. The scratch area must have a size that is enough to store at least the largest sector that is going to be swapped. Many devices have small equally sized flash sectors, eg 4K, while others have variable sized sectors where the largest sectors might be 128K or 256K, so the scratch must be big enough to store that. The scratch is only ever used when swapping firmware, which means only when doing an upgrade. Given that, the main reason for using a larger size for the scratch is that flash wear will be more evenly distributed, because a single sector would be written twice the number of times than using two sectors, for example. To evaluate the ideal size of the scratch for your use case the following parameters are relevant:
ブートローダは、イメージ領域のスロットに加えて、確実にイメージを交換できるようにscratch領域を必要とする。scratch領域は、少なくとも交換される最大セクタを格納するのに十分なサイズでなければならない。多くのデバイスでは、4K などの小さいサイズのフラッシュセクタがあるが、最大のセクタは 128K や 256K などの可変サイズのセクタもあるので、scratch領域はそれを格納するのに十分な大きさでなければならない。scratchは、ファームウェアを交換するとき、つまりアップグレードを行うときにのみ使用される。したがって、scratchのサイズを大きくすることでフラッシュの損耗を均等に分散することができる。例えばサイズを二倍にすることで書込み頻度は半分になる。scratchの理想的サイズの検討には以下のパラメータが必要である。

  • the ratio of image size / scratch size
  • the number of erase cycles supported by the flash hardware

The image size is used (instead of slot size) because only the slot's sectors that are actually used for storing the image are copied. The image/scratch ratio is the number of times the scratch will be erased on every upgrade. The number of erase cycles divided by the image/scratch ratio will give you the number of times an upgrade can be performed before the device goes out of spec.
実際にイメージが格納されるスロットのセクタのみがコピーされるため、スロットサイズではなくイメージサイズを使用する。イメージ/scratch の値は、アップグレードのたびにscratchが消去される回数を示す。消去回数をイメージ/scratchの値で割ったものが、デバイスで定められた仕様の範囲内でアップグレードを実行できる回数となる。

num_upgrades = number_of_erase_cycles / (image_size / scratch_size)

Let's assume, for example, a device with 10000 erase cycles, an image size of 150K and a scratch of 4K (usual minimum size of 4K sector devices). This would result in a total of:
例えば、デバイスの消去回数を10000回、イメージサイズ150K、scratchサイズ4K(通常の4Kセクターデバイスの最小サイズ)を想定したとき、アップグレード可能回数は以下の通り。

10000 / (150 / 4) ~ 267

Increasing the scratch to 16K would give us:
scratchを16Kに増やすと以下の回数となる。

10000 / (150 / 16) ~ 1067

There is no best ratio, as the right size is use-case dependent. Factors to consider include the number of times a device will be upgraded both in the field and during development, as well as any desired safety margin on the manufacturer's specified number of erase cycles. In general, using a ratio that allows hundreds to thousands of field upgrades in production is recommended.
適切なサイズはユースケースに依存するため、ベストな比率というものはない。考慮すべき要因には、デバイスが稼働後と開発過程の双方でアップグレードされる回数や、メーカーが指定した消去サイクル数に対する安全マージンなどがある。一般的には、数百から数千回のフィールドアップグレードを可能にする比率を使用することを推奨する。

Equal slots (direct-xip)

When the direct-xip mode is enabled the active image flag is "moved" between the slots during image upgrade and in contrast to the above, the bootloader can run an image directly from either the primary or the secondary slot (without having to move/copy it into the primary slot). Therefore the image update client, which downloads the new images must be aware, which slot contains the active image and which acts as a staging area and it is responsible for loading the proper images into the proper slot. All this requires that the images be built to be executed from the corresponding slot. At boot time the bootloader first looks for images in the slots and then inspects the version numbers in the image headers. It selects the newest image (with the highest version number) and then checks its validity (integrity check, signature verification etc.). If the image is invalid MCUboot erases its memory slot and starts to validate the other image. After a successful validation of the selected image the bootloader chain-loads it.
Direct-xip モードが有効な場合、イメージアップグレード中にアクティブなイメージフラグはスロット間で「移動」され、上記とは対照的に、ブートローダはprimary slotまたはsecondary slotから直接イメージを実行することができる (primary slotに移動/コピーする必要はない)。そのため、新しいイメージをダウンロードするイメージ更新クライアントは、どのスロットにアクティブなイメージがあり、どちらがステージングエリアとして機能しているかを認識し、適切なスロットに適切なイメージをロードする責任がある。これらはすべて、対応するスロットから実行されるようにイメージを構築する必要がある。ブート時には、ブートローダはまずスロット内のイメージを探し、イメージヘッダのバージョン番号を調べる。最新のイメージ(バージョン番号が最も高いもの)を選択し、その有効性をチェックする(整合性チェック、署名検証など)。もしイメージが無効な場合、MCUbootはメモリスロットを消去し、他のイメージの検証を開始する。選択されたイメージの検証が成功すると、ブートローダはそれをチェーンロードする。

Handling the primary and secondary slots as equals has its drawbacks. Since the images are not moved between the slots, the on-the-fly image encryption/decryption can't be supported (it only applies to storing the image in an external flash on the device, the transport of encrypted image data is still feasible).
primary slotとsecondary slotを対等に扱うことには欠点がある。イメージはスロット間で移動しないので、その場でのイメージの暗号化/復号はサポートされない (デバイス上の外部フラッシュにイメージを保存する場合にのみ適用される。)

The overwrite and the direct-xip upgrade strategies are substantially simpler to implement than the image swapping strategy, especially since the bootloader must work properly even when it is reset during the middle of an image swap. For this reason, the rest of the document describes its behavior when configured to swap images during an upgrade.
上書きや direct-xip アップグレード戦略は、イメージ交換戦略よりも実装がかなり簡単である。このため、この文書の残りの部分では、アップグレード中にイメージを交換するように設定した場合の動作を説明する。

RAM Loading

In ram-load mode the slots are equal. Like the direct-xip mode, this mode also selects the newest image by reading the image version numbers in the image headers. But instead of executing it in place, the newest image is copied to the RAM for execution. The load address, the location in RAM where the image is copied to, is stored in the image header. The ram-load upgrade mode can be useful when there is no internal flash in the SoC, but there is a big enough internal RAM to hold the images. Usually in this case the images are stored in an external storage device. Execution from external storage has some drawbacks (lower execution speed, image is exposed to attacks) therefore the image is always copied to the internal RAM before the authentication and execution. Ram-load mode requires the image to be built to be executed from the RAM address range instead of the storage device address range. If ram-load is enabled then platform must define the following parameters:
ram-loadモードにおいても、二つのスロットの役割は同じになる。このモードもDirect-xipモードと同様に、イメージヘッダのイメージのバージョン番号を読み込んで最新のイメージを選択する。ただし、その場で実行するのではなく、最新のイメージがRAMにコピーされて実行される。ロードアドレス、つまりイメージがコピーされるRAM内の場所は、イメージヘッダーに格納されている。ram-loadアップグレード・モードは、SoCに内蔵フラッシュがないが、イメージを保持するのに十分な大きさの内蔵RAMがある場合に便利である。通常、この場合、イメージは外部記憶装置に保存される。外部記憶装置からの実行にはいくつかの欠点がある(実行速度が低下する、イメージが攻撃にさらされる)ため、認証と実行の前にイメージは常に内部RAMにコピーされる。ram-loadモードでは、イメージはストレージデバイスのアドレス範囲ではなく、RAMのアドレス範囲から実行されるようにビルドする必要がある。ram-loadが有効な場合、プラットフォームは以下のパラメータを定義する必要がある。

#define IMAGE_EXECUTABLE_RAM_START    <area_base_addr>
#define IMAGE_EXECUTABLE_RAM_SIZE     <area_size_in_bytes>

When ram-load is enabled, the --load-addr <addr> option of the imgtool script must also be used when signing the images. This option set the RAM_LOAD flag in the image header which indicates that the image should be loaded to the RAM and also set the load address in the image header.
ram-loadが有効な場合、imgtool スクリプトの --load-addr <addr> オプションをイメージに署名する際にも使用しなければならない。このオプションはイメージヘッダに RAM_LOAD フラグを設定し、イメージを RAM にロードすることを示す。

The ram-load mode currently supports only the single image boot and the image encryption feature is not supported.
現在のところ、ram-loadモードは単一のイメージの起動のみをサポートしており、イメージの暗号化機能はサポートされていない。

Boot Swap Types

When the device first boots under normal circumstances, there is an up-to-date firmware image in each primary slot, which mcuboot can validate and then chain-load. In this case, no image swaps are necessary. During device upgrades, however, new candidate image(s) is present in the secondary slot(s), which mcuboot must swap into the primary slot(s) before booting as discussed above.
通常の状況下でデバイスが最初に起動すると、各primary slotに最新のファームウェアイメージがあり、mcubootはそれを検証してからチェーンロードする。この場合、イメージの交換は必要ない。一方、デバイスのアップグレードの際には、secondary slotに新しいイメージの候補が存在する。

Upgrading an old image with a new one by swapping can be a two-step process. In this process, mcuboot performs a "test" swap of image data in flash and boots the new image or it will be executed during operation. The new image can then update the contents of flash at runtime to mark itself "OK", and mcuboot will then still choose to run it during the next boot. When this happens, the swap is made "permanent". If this doesn't happen, mcuboot will perform a "revert" swap during the next boot by swapping the image(s) back into its original location(s) , and attempting to boot the old image(s).
交換によるイメージのアップグレードは、2段階で行われる。まず、mcuboot はフラッシュ内のイメージデータの「test」交換を実行し、新しいイメージを起動する。新しいイメージは、実行時にフラッシュの情報を更新して自分自身を「OK」とマークし、mcubootの次の起動時にも新しいイメージが選択されて実行されるようにする。この手続きにより交換は「permanent」になる。この手続きが行われなかった場合、mcubootは次のブート時に古いイメージを元の場所に戻してブートすることで、交換は「revert」される。

Depending on the use case, the first swap can also be made permanent directly. In this case, mcuboot will never attempt to revert the images on the next reset.
ユースケースによっては、最初の交換の時点で「permanent」とすることもできる。この場合、mcubootは次のリセット時にイメージを元に戻そうとはしない。

Test swaps are supported to provide a rollback mechanism to prevent devices from becoming "bricked" by bad firmware. If the device crashes immediately upon booting a new (bad) image, mcuboot will revert to the old (working) image at the next device reset, rather than booting the bad image again. This allows device firmware to make test swaps permanent only after performing a self-test routine.
「test」交換は、不良ファームウェアによるデバイスの「故障」を防ぐためのロールバック機構を提供するためにサポートされている。新しい(不良)イメージを起動した直後にデバイスがクラッシュした場合、mcubootは次のデバイスリセット時に不良イメージを再度起動するのではなく、古い(動作している)イメージに戻す。これにより、デバイスのファームウェアは、セルフテストルーチンを実行した後にのみ、「test」交換を「Permanent」とすることができる。

On startup, mcuboot inspects the contents of flash to decide for each images which of these "swap types" to perform; this decision determines how it proceeds.
起動時に、mcubootはフラッシュの内容を検査して、イメージ毎にどの「swap type」を実行するかを決定する。

The possible swap types, and their meanings, are:
「swap type」の種類とそれぞれの意味は以下の通り。

  • BOOT_SWAP_TYPE_NONE: The "usual" or "no upgrade" case; attempt to boot the contents of the primary slot.
    通常時または非アップグレード時。primary slotからのブートを試みる。

  • BOOT_SWAP_TYPE_TEST: Boot the contents of the secondary slot by swapping images. Unless the swap is made permanent, revert back on the next boot.
    secondary slotのイメージを交換してブートする。交換が「permanent」にならなかった場合は、次のブート時に「revert」交換が行われる。

  • BOOT_SWAP_TYPE_PERM: Permanently swap images, and boot the upgraded image firmware.
    「permanent」でイメージを交換し、アップグレードされたイメージをブートする。

  • BOOT_SWAP_TYPE_REVERT: A previous test swap was not made permanent; swap back to the old image whose data are now in the secondary slot. If the old image marks itself "OK" when it boots, the next boot will have swap type BOOT_SWAP_TYPE_NONE.
    前回の「test」交換が「permanent」にならなかった場合。現在secondary slotに存在する古いイメージを戻す。古いイメージが自身を「OK」と記録すると、次回ブート時のswap typeはBOOT_SWAP_TYPE_NONEとなる。

  • BOOT_SWAP_TYPE_FAIL: Swap failed because image to be run is not valid.
    起動すべきイメージに問題があったことによる交換失敗。

  • BOOT_SWAP_TYPE_PANIC: Swapping encountered an unrecoverable error.
    回復不能なエラーによる交換失敗。

The "swap type" is a high-level representation of the outcome of the boot. Subsequent sections describe how mcuboot determines the swap type from the bit-level contents of flash.
「swap type」は、ブートの結果を高レベルで表現したものである。以降のセクションでは、mcuboot がフラッシュのビットレベルの情報からswap typeを判定する方法を説明する。

Image Trailer

For the bootloader to be able to determine the current state and what actions should be taken during the current boot operation, it uses metadata stored in the image flash areas. While swapping, some of this metadata is temporarily copied into and out of the scratch area.
ブートローダが現在の状態や、現在のブート動作中にどのようなアクションを取るべきかを判定するために、イメージフラッシュ領域に格納されているメタデータを使用する。イメージ交換中に、このメタデータの一部がscratch領域に一時的にコピーされたり、scratch領域からコピーされたりする。

This metadata is located at the end of the image flash areas, and is called an image trailer. An image trailer has the following structure:
このメタデータはイメージフラッシュ領域の末尾にあり、image trailerと呼ばれている。image trailerは、次の構造になっている。

     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) [*]              |
    |                                                               |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                 Encryption key 1 (16 octets) [*]              |
    |                                                               |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                      Swap size (4 octets)                     |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |   Swap info   |           0xff padding (7 octets)             |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |   Copy done   |           0xff padding (7 octets)             |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |   Image OK    |           0xff padding (7 octets)             |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                       MAGIC (16 octets)                       |
    |                                                               |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

[*]: Only present if the encryption option is enabled (MCUBOOT_ENC_IMAGES).
暗号化オプション(MCUBOOT_ENC_IMAGES)が有効な場合のみ存在。

The offset immediately following such a record represents the start of the next flash area.
このレコードに続くオフセットは、次のフラッシュ領域の開始を表す。

Note: "min-write-size" is a property of the flash hardware. If the hardware allows individual bytes to be written at arbitrary addresses, then min-write-size is 1. If the hardware only allows writes at even addresses, then min-write-size is 2, and so on.
注:「min-write-size」はフラッシュ・ハードウェアの属性である。ハードウェアが任意のアドレスへの書き込みを許可している場合はmin-write-sizeは1、偶数アドレスへの書き込みしか許可していない場合はmin-write-sizeは2となる。

An image trailer contains the following fields:
image trailerは以下のフィールドで構成される。

  • Swap status: A series of records which records the progress of an image swap. To swap entire images, data are swapped between the two image areas one or more sectors at a time, like this:
    イメージ交換の進行状況を記録する一連のレコード。イメージ全体を交換するには、以下のように2つのイメージ領域の間で1つまたは複数のセクタずつデータを交換する。

    • sector data in the primary slot is copied into scratch, then erased primary slotのセクタデータはscratchにコピーされ、消去される。
    • sector data in the secondary slot is copied into the primary slot, then erased secondary slotのセクタデータがprimary slotにコピーされ、消去される。
    • sector data in scratch is copied into the secondary slot scratchのセクタデータをsecondary slotにコピーする。

As it swaps images, the bootloader updates the swap status field in a way that allows it to compute how far this swap operation has progressed for each sector. The swap status field can thus used to resume a swap operation if the bootloader is halted while a swap operation is ongoing and later reset. The BOOT_MAX_IMG_SECTORS value is the configurable maximum number of sectors mcuboot supports for each image; its value defaults to 128, but allows for either decreasing this size, to limit RAM usage, or to increase it in devices that have massive amounts of Flash or very small sized sectors and thus require a bigger configuration to allow for the handling of all slot's sectors. The factor of min-write-sz is due to the behavior of flash hardware. The factor of 3 is explained below.
イメージを交換すると、ブートローダはswap statusフィールドを更新して、セクタごとに交換処理がどの程度進んでいるかを計算する。これにより、交換処理中にブートローダが停止し、後でリセットされた場合に、交換処理を再開するためにswap statusフィールドを使用することができる。デフォルトは 128 ですが、RAM の使用量を制限するためにこのサイズを小さくしたり、大量のフラッシュや非常に小さなセクタを持つデバイスでは大きくしたりして、すべてのスロットのセクタを処理できるようにするために大きな設定を必要としたりすることができる。min-write-szの係数は、フラッシュハードウェアの挙動によるものである。以下で3のファクターについて説明する。

  • Encryption keys: key-encrypting keys (KEKs). These keys are needed for image encryption and decryption. See the encrypted images document for more information.
    これらの鍵は、イメージの暗号化と復号に必要である。 詳細はencrypted_images.mdドキュメントを参照のこと。

  • Swap size: When beginning a new swap operation, the total size that needs to be swapped (based on the slot with largest image + TLVs) is written to this location for easier recovery in case of a reset while performing the swap.
    新しい交換処理を開始するにあたり、交換処理の実行中にリセットされた場合の復旧を容易にするために、交換処理を実行する必要がある合計サイズ(最大イメージ+TLVのスロットに基づく)がこの場所に書き込まれる。

  • Swap info: A single byte which encodes the following information:
    以下の情報を記録する1 byte値。

    • Swap type: Stored in bits 0-3. Indicating the type of swap operation in progress. When mcuboot resumes an interrupted swap, it uses this field to determine the type of operation to perform. This field contains one of the following values in the table below. 0~3ビットに格納される。進行中のswap typeを示す。mcubootが中断されたイメージ交換を再開するとき、mcubootはこのフィールドを使用して実行するswap typeを決定する。このフィールドには、以下の表のいずれかの値が含まれる。
    • Image number: Stored in bits 4-7. It has always 0 value at single image boot. In case of multi image boot it indicates, which image was swapped when interrupt happened. The same scratch area is used during in case of all image swap operation. Therefore this field is used to determine which image the trailer belongs to if boot status is found on scratch area when the swap operation is resumed. 4-7ビットに格納される。シングルイメージブート時には常に0になる。マルチイメージブートの場合は、割り込みが発生したときにどのイメージが交換されたかを示す。全てのイメージ交換の場合、同じscratch領域が使用される。そのため、イメージ交換を再開した際にscratch領域にブートステータスが見つかった場合に、image trailerがどのイメージに属するかを判断するために使用する。
Name Value
BOOT_SWAP_TYPE_TEST 2
BOOT_SWAP_TYPE_PERM 3
BOOT_SWAP_TYPE_REVERT 4
  • Copy done: A single byte indicating whether the image in this slot is complete (0x01=done; 0xff=not done).
    このスロット内のイメージが完全であるかどうかを示す1 byte値。

  • Image OK: A single byte indicating whether the image in this slot has been confirmed as good by the user (0x01=confirmed; 0xff=not confirmed).
    このスロット内のイメージが問題ないことがユーザによって確認済であることを示す1 byte値。

  • MAGIC: The following 16 bytes, written in host-byte-order:
    host-byte-orderで記録される以下の16 byte値。

    const uint32_t boot_img_magic[4] = {
        0xf395c277,
        0x7fefd260,
        0x0f505235,
        0x8079b62c,
    };

IMAGE TRAILERS

At startup, the boot loader determines the boot swap type by inspecting the image trailers. When using the term "image trailers" what is meant is the aggregate information provided by both image slot's trailers.
起動時に、ブートローダはimage trailersを検査してswap typeを決定する。 「image trailers」という用語を使う場合、意味するのは、双方のイメージスロットに対するimage trailerの情報全体を表す。

New swaps (non-resumes)

For new swaps, mcuboot must inspect a collection of fields to determine which swap operation to perform.
交換処理の開始にあたり、mcubootはどの交換処理を実施するかを決定するために、フィールドの集合を検査しなければならない。

The image trailers records are structured around the limitations imposed by flash hardware. As a consequence, they do not have a very intuitive design, and it is difficult to get a sense of the state of the device just by looking at the
image trailers. It is better to map all the possible trailer states to the swap types described above via a set of tables. These tables are reproduced below.
image trailersのレコードは、フラッシュハードウェアの制約を受けて構成されており、あまり直感的なデザインにはなっていない。image trailersを見るだけでデバイスの状態を把握するのは困難である。発生し得るimage trailersの状態を、表を使って上述のswap typeに照らし合わせるのが良い。image trailersの状態を示す表を以下に示す。

Note: An important caveat about the tables described below is that they must be evaluated in the order presented here. Lower state numbers must have a higher priority when testing the image trailers.
注意:以下の表についての重要な点は、ここで紹介した順番で評価しなければならないということである。image trailersの確認にあたり、Stete番号が小さい方が優先度が高くなる。

    State I
                     | primary slot | secondary slot |
    -----------------+--------------+----------------|
               magic | Any          | Good           |
            image-ok | Any          | Unset          |
           copy-done | Any          | Any            |
    -----------------+--------------+----------------'
     result: BOOT_SWAP_TYPE_TEST                     |
    -------------------------------------------------'


    State II
                     | primary slot | secondary slot |
    -----------------+--------------+----------------|
               magic | Any          | Good           |
            image-ok | Any          | 0x01           |
           copy-done | Any          | Any            |
    -----------------+--------------+----------------'
     result: BOOT_SWAP_TYPE_PERM                     |
    -------------------------------------------------'


    State III
                     | primary slot | secondary slot |
    -----------------+--------------+----------------|
               magic | Good         | Unset          |
            image-ok | 0xff         | Any            |
           copy-done | 0x01         | Any            |
    -----------------+--------------+----------------'
     result: BOOT_SWAP_TYPE_REVERT                   |
    -------------------------------------------------'

Any of the above three states results in mcuboot attempting to swap images.
上記の 3 つの状態のいずれかになると、mcuboot はイメージの交換を試みる。

Otherwise, mcuboot does not attempt to swap images, resulting in one of the other three swap types, as illustrated by State IV.
そうでなければ、mcubootはイメージの交換を行わず、その結果、State IVに示すように、他の3つのswap typeのうちの1つになる。

    State IV
                     | primary slot | secondary slot |
    -----------------+--------------+----------------|
               magic | Any          | Any            |
            image-ok | Any          | Any            |
           copy-done | Any          | Any            |
    -----------------+--------------+----------------'
     result: BOOT_SWAP_TYPE_NONE,                    |
             BOOT_SWAP_TYPE_FAIL, or                 |
             BOOT_SWAP_TYPE_PANIC                    |
    -------------------------------------------------'

In State IV, when no errors occur, mcuboot will attempt to boot the contents of the primary slot directly, and the result is BOOT_SWAP_TYPE_NONE. If the image in the primary slot is not valid, the result is BOOT_SWAP_TYPE_FAIL. If a fatal error occurs during boot, the result is BOOT_SWAP_TYPE_PANIC. If the result is either BOOT_SWAP_TYPE_FAIL or BOOT_SWAP_TYPE_PANIC, mcuboot hangs rather than booting an invalid or compromised image.
State IVにおいて、エラーが発生しなかった場合は、mcubootはprimary slotの内容を直接起動しようとし、その結果は BOOT_SWAP_TYPE_NONEである。primary slotのイメージが有効でない場合、結果は BOOT_SWAP_TYPE_FAIL である。起動中に致命的なエラーが発生した場合、結果は BOOT_SWAP_TYPE_PANIC である。結果が BOOT_SWAP_TYPE_FAILBOOT_SWAP_TYPE_PANIC の場合、mcuboot は無効なイメージや危殆化したイメージを起動するのではなくハングする。

Note: An important caveat to the above is the result when a swap is requested and the image in the secondary slot fails to validate, due to a hashing or signing error. This state behaves as State IV with the extra action of marking the image in the primary slot as "OK", to prevent further attempts to swap.
注意: 上記の重要な点は、交換処理が要求され、secondary slotのイメージがハッシュエラーや署名エラーのために検証に失敗した場合の結果である。この状態はState IVのように振る舞うが、primary slotのイメージを「OK」とマークして、再度の交換処理を行わないようにしている。

Resumed swaps

If mcuboot determines that it is resuming an interrupted swap (i.e., a reset occurred mid-swap), it fully determines the operation to resume by reading the swap info field from the active trailer and extracting the swap type from bits
0-3. The set of tables in the previous section are not necessary in the resume case.
mcubootが中断された交換処理(すなわち、交換処理の途中でリセットが発生した)を再開すると判断した場合、アクティブなimage trailerから swap info フィールドを読み込み、0-3 bitからswap typeを抽出することで、再開する操作を決定します。
前のセクションの表を使った判定は、再開処理の場合は不要です。

High-Level Operation

With the terms defined, we can now explore the boot loader's operation. First, a high-level overview of the boot process is presented. Then, the following sections describe each step of the process in more detail.
用語が定義されたので、ブートローダの動作を調べてみましょう。 最初に、ブートプロセスのハイレベルな概要を説明します。 以降のセクションでは、プロセスの各ステップをより詳細に説明します。

Procedure:

  • Inspect swap status region; is an interrupted swap being resumed?
    swap status領域の検査:交換処理の再開か?

    • Yes: Complete the partial swap operation; skip to step 3. 中断された交換処理を完了させてStep 3へ。
    • No: Proceed to step 2. Step 2へ。
  • Inspect image trailers; is a swap requested?
    image trailersの検査:交換処理が必要か?

    • Yes: Is the requested image valid (integrity and security check)? 交換対象のイメージに問題は無いか(ハッシュや署名は正しいか)?
      • Yes.
        • Perform swap operation. 交換処理を実行。
        • Persist completion of swap procedure to image trailers. image trailersに交換処理の完了を記録。
        • Proceed to step 3. Step 3へ。
      • No.
        • Erase invalid image. 問題のあるイメージを削除。
        • Persist failure of swap procedure to image trailers. image trailersに交換処理の失敗を記録。
        • Proceed to step 3. Step 3へ。
    • No: Proceed to step 3. Step 3へ。
  • Boot into image in primary slot.
    primary slotのイメージを起動。

Multiple Image Boot

When the flash contains multiple executable images the boot loader's operation is a bit more complex but similar to the previously described procedure with one image. Every image can be updated independently therefore the flash is partitioned further to arrange two slots for each image.
フラッシュに複数の実行可能なイメージが含まれている場合、ブートローダの処理は少し複雑にはなりますが、手順は1つのイメージで説明したのと同様です。各イメージは独立して更新することができるので、フラッシュはさらに分割され、各イメージ用に2つのスロットが配置されます。

+--------------------+
| MCUBoot            |
+--------------------+
        ~~~~~            <- memory might be not contiguous
+--------------------+
| Image 0            |
| primary   slot     |
+--------------------+
| Image 0            |
| secondary slot     |
+--------------------+
        ~~~~~            <- memory might be not contiguous
+--------------------+
| Image N            |
| primary   slot     |
+--------------------+
| Image N            |
| secondary slot     |
+--------------------+
| Scratch            |
+--------------------+

MCUBoot is also capable of handling dependencies between images. For example if an image needs to be reverted it might be necessary to revert another one too (e.g. due to API incompatibilities) or simply to prevent from being updated because of an unsatisfied dependency. Therefore all aborted swaps have to be completed and all the swap types have to be determined for each image before the dependency checks. Dependency handling is described in more detail in a following section. The multiple image boot procedure is organized in loops which iterate over all the firmware images. The high-level overview of the boot process is presented below.
MCUBoot は、イメージ間の依存関係を扱うこともできます。例えば、あるイメージを元に戻す必要がある場合、別のイメージも元に戻す必要があるかもしれません(API の非互換性など)。そのためには、中断された交換はすべて完了させ、依存性チェックの前に各イメージのswap typeを決定しておく必要があります。依存関係の処理については、次の節で詳しく説明します。複数のイメージのブート手順は、すべてのファームウェアイメージを反復するループで構成されます。以下に、ブートプロセスのハイレベルな概要を示します。

  • Loop 1. Iterate over all images

    • Inspect swap status region of current image; is an interrupted swap being resumed?
      • Yes:
        • Review the validity of previously determined swap types of other images.
        • Complete the partial swap operation.
        • Mark the swap type as None.
        • Skip to next image.
      • No: Proceed to step 2.
    • Inspect image trailers in the primary and secondary slot; is an image swap requested?
      • Yes: Review the validity of previously determined swap types of other images. Is the requested image valid (integrity and security check)?
        • Yes:
          • Set the previously determined swap type for the current image.
          • Skip to next image.
        • No:
          • Erase invalid image.
          • Persist failure of swap procedure to image trailers.
          • Mark the swap type as Fail.
          • Skip to next image.
      • No:
        • Mark the swap type as None.
        • Skip to next image.
  • Loop 2. Iterate over all images

    • Does the current image depend on other image(s)?
      • Yes: Are all the image dependencies satisfied?
        • Yes: Skip to next image.
        • No:
          • Modify swap type depending on what the previous type was.
          • Restart dependency check from the first image.
      • No: Skip to next image.
  • Loop 3. Iterate over all images

    • Is an image swap requested?
      • Yes:
        • Perform image update operation.
        • Persist completion of swap procedure to image trailers.
        • Skip to next image.
      • No: Skip to next image.
  • Loop 4. Iterate over all images

    • Validate image in the primary slot (integrity and security check) or at least do a basic sanity check to avoid booting into an empty flash area.
  • Boot into image in the primary slot of the 0th image position (other image in the boot chain is started by another image).

Image Swapping

The boot loader swaps the contents of the two image slots for two reasons:

  • User has issued a "set pending" operation; the image in the secondary slot should be run once (state I) or repeatedly (state II), depending on whether a permanent swap was specified.
  • Test image rebooted without being confirmed; the boot loader should revert to the original image currently in the secondary slot (state III).

If the image trailers indicates that the image in the secondary slot should be
run, the boot loader needs to copy it to the primary slot. The image currently
in the primary slot also needs to be retained in flash so that it can be used
later. Furthermore, both images need to be recoverable if the boot loader
resets in the middle of the swap operation. The two images are swapped
according to the following procedure:

  1. Determine if both slots are compatible enough to have their images swapped. To be compatible, both have to have only sectors that can fit into the scratch area and if one of them has larger sectors than the other, it must be able to entirely fit some rounded number of sectors from the other slot. In the next steps we'll use the terminology "region" for the total amount of data copied/erased because this can be any amount of sectors depending on how many the scratch is able to fit for some swap operation.
  2. Iterate the list of region indices in descending order (i.e., starting with the greatest index); only regions that are predetermined to be part of the image are copied; current element = "index".
    • a. Erase scratch area.
    • b. Copy secondary_slot[index] to scratch area.
      • If this is the last region in the slot, scratch area has a temporary status area initialized to store the initial state, because the primary slot's last region will have to be erased. In this case, only the data that was calculated to amount to the image is copied.
      • Else if this is the first swapped region but not the last region in the slot, initialize the status area in primary slot and copy the full region contents.
      • Else, copy entire region contents.
    • c. Write updated swap status (i).
    • d. Erase secondary_slot[index]
    • e. Copy primary_slot[index] to secondary_slot[index] according to amount previosly copied at step b.
      • If this is not the last region in the slot, erase the trailer in the secondary slot, to always use the one in the primary slot.
    • f. Write updated swap status (ii).
    • g. Erase primary_slot[index].
    • h. Copy scratch area to primary_slot[index] according to amount previously copied at step b.
      • If this is the last region in the slot, the status is read from scratch (where it was stored temporarily) and written anew in the primary slot.
    • i. Write updated swap status (iii).
  3. Persist completion of swap procedure to the primary slot image trailer.

The additional caveats in step 2f are necessary so that the secondary slot image
trailer can be written by the user at a later time. With the image trailer
unwritten, the user can test the image in the secondary slot
(i.e., transition to state I).

Note1: If the region being copied contains the last sector, then swap status is
temporarily maintained on scratch for the duration of this operation, always
using the primary slot's area otherwise.

Note2: The bootloader tries to copy only used sectors (based on largest image
installed on any of the slots), minimizing the amount of sectors copied and
reducing the amount of time required for a swap operation.

The particulars of step 3 vary depending on whether an image is being tested,
permanently used, reverted or a validation failure of the secondary slot
happened when a swap was requested:

* test:
    o Write primary_slot.copy_done = 1
    (swap caused the following values to be written:
        primary_slot.magic = BOOT_MAGIC
        secondary_slot.magic = UNSET
        primary_slot.image_ok = Unset)

* permanent:
    o Write primary_slot.copy_done = 1
    (swap caused the following values to be written:
        primary_slot.magic = BOOT_MAGIC
        secondary_slot.magic = UNSET
        primary_slot.image_ok = 0x01)

* revert:
    o Write primary_slot.copy_done = 1
    o Write primary_slot.image_ok = 1
    (swap caused the following values to be written:
        primary_slot.magic = BOOT_MAGIC)

* failure to validate the secondary slot:
    o Write primary_slot.image_ok = 1

After completing the operations as described above the image in the primary slot
should be booted.

Swap Status

The swap status region allows the boot loader to recover in case it restarts in the middle of an image swap operation. The swap status region consists of a series of single-byte records. These records are written independently, and therefore must be padded according to the minimum write size imposed by the flash hardware. In the below figure, a min-write-size of 1 is assumed for simplicity. The structure of the swap status region is illustrated below. In this figure, a min-write-size of 1 is assumed for simplicity.
swap status領域は、イメージ交換処理の途中でブートローダが再起動した場合に、 ブートローダが回復できるようにします。 swap status領域は、一連の1 byteレコードで構成されています。 これらのレコードは独立して書き込まれ、したがってフラッシュハードウェアの最小書き込みサイズに応じてパディングする必要があります。swap status領域の構造を以下に示します。 この図では、簡単のためにmin-write-sizeを1としています。

     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
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |sec127,state 0 |sec127,state 1 |sec127,state 2 |sec126,state 0 |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |sec126,state 1 |sec126,state 2 |sec125,state 0 |sec125,state 1 |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |sec125,state 2 |                                               |
    +-+-+-+-+-+-+-+-+                                               +
    ~                                                               ~
    ~               [Records for indices 124 through 1              ~
    ~                                                               ~
    ~               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    ~               |sec000,state 0 |sec000,state 1 |sec000,state 2 |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

The above is probably not helpful at all; here is a description in English.
上の図は参考にならないかもしれません。以下に英語で記載します。

Each image slot is partitioned into a sequence of flash sectors. If we were to enumerate the sectors in a single slot, starting at 0, we would have a list of sector indices. Since there are two image slots, each sector index would correspond to a pair of sectors. For example, sector index 0 corresponds to the first sector in the primary slot and the first sector in the secondary slot. Finally, reverse the list of indices such that the list starts with index BOOT_MAX_IMG_SECTORS - 1 and ends with 0. The swap status region is a representation of this reversed list.
各イメージスロットはフラッシュセクタの列に分割されています。1つのスロットのセクタを0から順に列挙すると、セクタインデックスのリストができます。 2つのイメージスロットがあるので、各セクタインデックスは1組のセクタに対応します。 例えば、セクタインデックス0は、primary slotの最初のセクタとsecondary slotの最初のセクタに対応します。最後に、インデックスのリストを逆にして BOOT_MAX_IMG_SECTORS - 1 で始まり 0 で終わるようにします。 swap status領域は、この逆にしたリストを表現したものです。

During a swap operation, each sector index transitions through four separate states:
交換処理の間、各セクタインデックスは4つの別々の状態に遷移します。

0. primary slot: image 0,   secondary slot: image 1,   scratch: N/A
1. primary slot: image 0,   secondary slot: N/A,       scratch: image 1 (1->s, erase 1)
2. primary slot: N/A,       secondary slot: image 0,   scratch: image 1 (0->1, erase 0)
3. primary slot: image 1,   secondary slot: image 0,   scratch: N/A     (s->0)

Each time a sector index transitions to a new state, the boot loader writes a
record to the swap status region. Logically, the boot loader only needs one
record per sector index to keep track of the current swap state. However, due
to limitations imposed by flash hardware, a record cannot be overwritten when
an index's state changes. To solve this problem, the boot loader uses three
records per sector index rather than just one.

Each sector-state pair is represented as a set of three records. The record
values map to the above four states as follows

            | rec0 | rec1 | rec2
    --------+------+------+------
    state 0 | 0xff | 0xff | 0xff
    state 1 | 0x01 | 0xff | 0xff
    state 2 | 0x01 | 0x02 | 0xff
    state 3 | 0x01 | 0x02 | 0x03

The swap status region can accommodate BOOT_MAX_IMG_SECTORS sector indices.
Hence, the size of the region, in bytes, is
BOOT_MAX_IMG_SECTORS * min-write-size * 3. The only requirement for the index
count is that it is great enough to account for a maximum-sized image
(i.e., at least as great as the total sector count in an image slot). If a
device's image slots have been configured with BOOT_MAX_IMG_SECTORS: 128 and
use less than 128 sectors, the first record that gets written will be somewhere
in the middle of the region. For example, if a slot uses 64 sectors, the first
sector index that gets swapped is 63, which corresponds to the exact halfway
point within the region.

Note: since the scratch area only ever needs to record swapping of the last
sector, it uses at most min-write-size * 3 bytes for its own status area.

Reset Recovery

If the boot loader resets in the middle of a swap operation, the two images may
be discontiguous in flash. Bootutil recovers from this condition by using the
image trailers to determine how the image parts are distributed in flash.

The first step is determine where the relevant swap status region is located.
Because this region is embedded within the image slots, its location in flash
changes during a swap operation. The below set of tables map image trailers
contents to swap status location. In these tables, the "source" field
indicates where the swap status region is located. In case of multi image boot
the images primary area and the single scratch area is always examined in pairs.
If swap status found on scratch area then it might not belong to the current
image. The swap_info field of swap status stores the corresponding image number.
If it does not match then "source: none" is returned.

              | primary slot | scratch      |
    ----------+--------------+--------------|
        magic | Good         | Any          |
    copy-done | 0x01         | N/A          |
    ----------+--------------+--------------'
    source: none                            |
    ----------------------------------------'

              | primary slot | scratch      |
    ----------+--------------+--------------|
        magic | Good         | Any          |
    copy-done | 0xff         | N/A          |
    ----------+--------------+--------------'
    source: primary slot                    |
    ----------------------------------------'

              | primary slot | scratch      |
    ----------+--------------+--------------|
        magic | Any          | Good         |
    copy-done | Any          | N/A          |
    ----------+--------------+--------------'
    source: scratch                         |
    ----------------------------------------'

              | primary slot | scratch      |
    ----------+--------------+--------------|
        magic | Unset        | Any          |
    copy-done | 0xff         | N/A          |
    ----------+--------------+--------------|
    source: primary slot                    |
    ----------------------------------------+------------------------------+
    This represents one of two cases:                                      |
    o No swaps ever (no status to read, so no harm in checking).           |
    o Mid-revert; status in the primary slot.                              |
    For this reason we assume the primary slot as source, to trigger a     |
    check of the status area and find out if there was swapping under way. |
    -----------------------------------------------------------------------'

If the swap status region indicates that the images are not contiguous, mcuboot
determines the type of swap operation that was interrupted by reading the swap
info
field in the active image trailer and extracting the swap type from bits
0-3 then resumes the operation. In other words, it applies the procedure defined
in the previous section, moving image 1 into the primary slot and image 0 into
the secondary slot. If the boot status indicates that an image part is present
in the scratch area, this part is copied into the correct location by starting
at step e or step h in the area-swap procedure, depending on whether the part
belongs to image 0 or image 1.

After the swap operation has been completed, the boot loader proceeds as though
it had just been started.

Integrity Check

An image is checked for integrity immediately before it gets copied into the primary slot. If the boot loader doesn't perform an image swap, then it can perform an optional integrity check of the image in the primary slot if MCUBOOT_VALIDATE_PRIMARY_SLOT is set, otherwise it doesn't perform an integrity check.
イメージがprimary slotにコピーされる直前に完全性のチェックが行われます。 ブートローダがイメージの交換を行わない場合、MCUBOOT_VALIDATE_PRIMARY_SLOTが設定されていればprimary slotイメージの完全性チェックが行われますが、そうでなければ整合性チェックは行いません。

During the integrity check, the boot loader verifies the following aspects of an image:
完全性チェックに際して、ブートローダはイメージの以下の点を確認します。

  • 32-bit magic number must be correct (IMAGE_MAGIC).
    32-bitのmagic numberが正しいこと(IMAGE_MAGIC)。

  • Image must contain an image_tlv_info struct, identified by its magic (IMAGE_TLV_PROT_INFO_MAGIC or IMAGE_TLV_INFO_MAGIC) exactly following the firmware (hdr_size + img_size). If IMAGE_TLV_PROT_INFO_MAGIC is found then after ih_protect_tlv_size bytes, another image_tlv_info with magic equal to IMAGE_TLV_INFO_MAGIC must be present.
    イメージがimage_tlv_info構造を含むこと。これはファームウェアの直後にあるmagic (IMAGE_TLV_PROT_INFO_MAGIC or IMAGE_TLV_INFO_MAGIC)で識別される。 IMAGE_TLV_PROT_INFO_MAGICが存在する場合は、ih_protect_tlv_sizeバイトの後に IMAGE_TLV_INFO_MAGICと等しいマジックを持つ別のimage_tlv_infoが存在しなければならない。

  • Image must contain a SHA256 TLV.
    イメージがSHA256 TLVを含むこと。

  • Calculated SHA256 must match SHA256 TLV contents.
    計算したSHA256値がSHA256 TLVと等しいこと。

  • Image may contain a signature TLV. If it does, it must also have a KEYHASH TLV with the hash of the key that was used to sign. The list of keys will then be iterated over looking for the matching key, which then will then be used to verify the image contents.
    イメージは署名TLVを含む場合がある。その場合は、署名に用いられた鍵のハッシュを含む KEYHASH TLV も存在しなければならない。鍵のリストは、一致する鍵を探して反復処理され、イメージの内容を検証するために使われます。

Security

As indicated above, the final step of the integrity check is signature verification. The boot loader can have one or more public keys embedded in it at build time. During signature verification, the boot loader verifies that an image was signed with a private key that corresponds to the embedded KEYHASH TLV.
上で述べたように、整合性チェックの最後のステップは署名検証です。 ブートローダは、ビルド時に 1 つ以上の公開鍵を埋め込むことができます。 署名検証の際、ブートローダはイメージが埋め込まれた KEYHASH TLV に対応する秘密鍵で署名されたことを検証します。

For information on embedding public keys in the boot loader, as well as producing signed images, see: signed_images.
ブートローダへの公開鍵の埋め込みや署名付きイメージの生成については、signed_images.mdを参照してください。

If you want to enable and use encrypted images, see: encrypted_images.
暗号化イメージを有効にして使用したい場合は、encrypted_images.mdを参照してください。

Note: Image encryption is not supported when the direct-xip or the ram-load upgrade strategy is selected.
注意: Direct-xip またはram-loadアップグレードが選択されている場合、イメージの暗号化はサポートされません。

Using Hardware Keys for Verification

By default, the whole public key is embedded in the bootloader code and its hash is added to the image manifest as a KEYHASH TLV entry. As an alternative the bootloader can be made independent of the keys by setting the MCUBOOT_HW_KEY option. In this case the hash of the public key must be provisioned to the target device and mcuboot must be able to retrieve the key-hash from there. For this reason the target must provide a definition for the boot_retrieve_public_key_hash() function which is declared in boot/bootutil/include/bootutil/sign_key.h. It is also required to use the full option for the --public-key-format imgtool argument in order to add the whole public key (PUBKEY TLV) to the image manifest instead of its hash (KEYHASH TLV). During boot the public key is validated before using it for signature verification, mcuboot calculates the hash of the public key from the TLV area and compares it with the key-hash that was retrieved from the device. This way mcuboot is independent from the public key(s). The key(s) can be provisioned any time and by different parties.
デフォルトでは、公開鍵全体がブートローダのコードに埋め込まれ、そのハッシュが KEYHASH TLV エントリとしてイメージマニフェストに追加されます。別の方法として、MCUBOOT_HW_KEY オプションを設定することで、 ブートローダを鍵から独立したものにすることができます。この場合、公開鍵のハッシュはターゲットデバイスにプロビジョニングされ、mcuboot はそこから鍵のハッシュを取得できなければなりません。この理由から、ターゲットは boot/bootutil/include/bootutil/sign_key.h で宣言されている boot_retrieve_public_key_hash()関数の定義を提供しなければなりません。また、ハッシュ (KEYHASH TLV) の代わりに公開鍵 (PUBKEY TLV) 全体をイメージマニフェストに追加するためには、--public-key-format imgtool の引数に full オプションを使用する必要があります。起動時に公開鍵が署名検証に使用される前に検証されると、mcuboot は TLV 領域から公開鍵のハッシュを計算し、デバイスから取得した鍵ハッシュと比較します。このようにして mcuboot は公開鍵から独立しています。鍵はいつでも、また異なるパーティによってプロビジョニングすることができます。

Protected TLVs

If the TLV area contains protected TLV entries, by beginning with a struct image_tlv_info with a magic value of IMAGE_TLV_PROT_INFO_MAGIC then the data of those TLVs must also be integrity and authenticity protected. Beyond the full size of the protected TLVs being stored in the image_tlv_info, the size of the protected TLVs together with the size of the image_tlv_info struct itself are also saved in the ih_protected_size field inside the header.
もしTLV領域に保護されたTLVエントリが含まれている場合、image_tlv_info構造体の先頭に IMAGE_TLV_PROT_INFO_MAGIC というマジック値を指定することで、それらのTLVのデータは完全性と真正性も保護されていなければならない。image_tlv_infoに保存される保護されたTLVのフルサイズの他に、保護されたTLVのサイズとimage_tlv_info構造体自体のサイズもヘッダ内のih_protected_size` フィールドに保存される。

Whenever an image has protected TLVs the SHA256 has to be calculated over not just the image header and the image but also the TLV info header and the protected TLVs.
画像が保護されたTLVを持つ場合、画像ヘッダと画像だけでなく、TLV infoヘッダと保護されたTLVも含めてSHA256を計算しなければならない。

A +---------------------+
  | Header              | <- struct image_header
  +---------------------+
  | Payload             |
  +---------------------+
  | TLV area            |
  | +-----------------+ |    struct image_tlv_info with
  | | TLV area header | | <- IMAGE_TLV_PROT_INFO_MAGIC (optional)
  | +-----------------+ |
  | | Protected TLVs  | | <- Protected TLVs (struct image_tlv)
B | +-----------------+ |
  | | TLV area header | | <- struct image_tlv_info with IMAGE_TLV_INFO_MAGIC
C | +-----------------+ |
  | | SHA256 hash     | | <- hash from A - B (struct image_tlv)
D | +-----------------+ |
  | | Keyhash         | | <- indicates which pub. key for sig (struct image_tlv)
  | +-----------------+ |
  | | Signature       | | <- signature from C - D (struct image_tlv), only hash
  | +-----------------+ |
  +---------------------+

Dependency Check

MCUBoot can handle multiple firmware images. It is possible to update them
independently but in many cases it can be desired to be able to describe
dependencies between the images (e.g. to ensure API compliance and avoid
interoperability issues).

The dependencies between images can be described with additional TLV entries in
the protected TLV area after the end of an image. There can be more than one
dependency entry, but in practice if the platform only supports two individual
images then there can be maximum one entry which reflects to the other image.

At the phase of dependency check all aborted swaps are finalized if there were
any. During the dependency check the boot loader verifies whether the image
dependencies are all satisfied. If at least one of the dependencies of an image
is not fulfilled then the swap type of that image has to be modified
accordingly and the dependency check needs to be restarted. This way the number
of unsatisfied dependencies will decrease or remain the same. There is always at
least 1 valid configuration. In worst case, the system returns to the initial
state after dependency check.

For more information on adding dependency entries to an image,
see: imgtool.

Downgrade Prevention

Downgrade prevention is a feature which enforces that the new image must have a higher version/security counter number than the image it is replacing, thus preventing the malicious downgrading of the device to an older and possibly vulnerable version of its firmware.
ダウングレード防止とは、新しいイメージが交換前のイメージよりも高いバージョン/セキュリティカウンター番号を持っていなければならないことを強制する機能であり、これによりファームウェアに脆弱性のある古いバージョンへの悪意のあるダウングレードからデバイスを守ります。

SW Based Downgrade Prevention

During the software based downgrade prevention the image version numbers are compared. This feature is enabled with the MCUBOOT_DOWNGRADE_PREVENTION option. In this case downgrade prevention is only available when the overwrite-based image update strategy is used (i.e. MCUBOOT_OVERWRITE_ONLY is set).
ソフトウェアベースのダウングレード防止では、イメージのバージョン番号の比較を行います。この機能は MCUBOOT_DOWNGRADE_PREVENTION オプションで有効になります。このダウングレード防止機能は、上書きベースのイメージ更新を使用する場合にのみ利用可能です(すなわち、MCUBOOT_OVERWRITE_ONLY が設定されている場合)。

HW Based Downgrade Prevention

Each signed image can contain a security counter in its protected TLV area, which can be added to the image using the -s option of the imgtool script. During the hardware based downgrade prevention (alias rollback protection) the new image's security counter will be compared with the currently active security counter value which must be stored in a non-volatile and trusted component of the device. It is beneficial to handle this counter independently from image version number:
各署名済みイメージは、その保護された TLV 領域にセキュリティカウンタを含めることができ、これは imgtool スクリプトの -s オプションを使用してイメージに追加することができます。ハードウェアベースのダウングレード防止(エイリアスロールバック保護)では、新しいイメージのセキュリティカウンタは、デバイスの不揮発性で信頼できるコンポーネントに格納されている必要がある現在のアクティブなセキュリティカウンタの値と比較されます。このカウンタは、イメージのバージョン番号とは独立して処理することが有益です。

  • It does not need to increase with each software release,
  • It makes it possible to do software downgrade to some extent: if the security counter has the same value in the older image then it is accepted.

It is an optional step of the image validation process and can be enabled with the MCUBOOT_HW_ROLLBACK_PROT config option. When enabled, the target must provide an implementation of the security counter interface defined in boot/bootutil/include/security_cnt.h.
これはイメージ検証プロセスのオプションのステップで、MCUBOOT_HW_ROLLBACK_PROT 設定オプションで有効にすることができます。有効にした場合、ターゲットは boot/bootutil/include/security_cnt.h で定義されているセキュリティカウンターインターフェイスの実装を提供しなければなりません。

Measured boot and data sharing

MCUBoot defines a mechanism for sharing boot status information (also known as
measured boot) and an interface for sharing application specific information
with the runtime software. If any of these are enabled the target must provide
a shared data area between the bootloader and runtime firmware and define the
following parameters:

#define MCUBOOT_SHARED_DATA_BASE    <area_base_addr>
#define MCUBOOT_SHARED_DATA_SIZE    <area_size_in_bytes>

In the shared memory area all data entries are stored in a type-length-value
(TLV) format. Before adding the first data entry, the whole area is overwritten
with zeros and a TLV header is added at the beginning of the area during an
initialization phase. This TLV header contains a tlv_magic field with a value
of SHARED_DATA_TLV_INFO_MAGIC and a tlv_tot_len field which is indicating
the total length of shared TLV area including this header. The header is
followed by the the data TLV entries which are composed from a
shared_data_tlv_entry header and the data itself. In the data header there is
a tlv_type field which identifies the consumer of the entry (in the runtime
software) and specifies the subtype of that data item. More information about
the tlv_type field and data types can be found in the
boot/bootutil/include/bootutil/boot_status.h file. The type is followed by a
tlv_len field which indicates the size of the data entry in bytes, not
including the entry header. After this header structure comes the actual data.

/** Shared data TLV header.  All fields in little endian. */
struct shared_data_tlv_header {
    uint16_t tlv_magic;
    uint16_t tlv_tot_len; /* size of whole TLV area (including this header) */
};

/** Shared data TLV entry header format. All fields in little endian. */
struct shared_data_tlv_entry {
    uint16_t tlv_type;
    uint16_t tlv_len; /* TLV data length (not including this header). */
};

The measured boot can be enabled with the MCUBOOT_MEASURED_BOOT config option.
When enabled, the --boot_record argument of the imgtool script must also be
used during the image signing process to add a BOOT_RECORD TLV to the image
manifest. This TLV contains the following attributes/measurements of the
image in CBOR encoded format:

  • Software type (role of the software component)
  • Software version
  • Signer ID (identifies the signing authority)
  • Measurement value (hash of the image)
  • Measurement type (algorithm used to calculate the measurement value)

The sw_type string that is passed as the --boot_record option's parameter
will be the value of the "Software type" attribute in the generated BOOT_RECORD
TLV. The target must also define the MAX_BOOT_RECORD_SZ macro which indicates
the maximum size of the CBOR encoded boot record in bytes.
During boot, MCUBoot will look for these TLVs (in case of multiple images) in
the manifests of the active images (the latest and validated) and copy the CBOR
encoded binary data to the shared data area. Preserving all these image
attributes from the boot stage for use by later runtime services (such as an
attestation service) is known as a measured boot.

Setting the MCUBOOT_DATA_SHARING option enables the sharing of application
specific data using the same shared data area as for the measured boot. For
this, the target must provide a definition for the boot_save_shared_data()
function which is declared in boot/bootutil/include/bootutil/boot_record.h.
The boot_add_data_to_shared_area() function can be used for adding new TLV
entries to the shared data area.

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0