blob: 12d68eeb2152028a407d5f60280686cd731fbea9 [file] [log] [blame] [view]
David Brown17e20d12017-09-12 11:53:20 -06001<!--
David Brownaac71112020-02-03 16:13:42 -07002 - SPDX-License-Identifier: Apache-2.0
David Brown17e20d12017-09-12 11:53:20 -06003
David Vinczee574f2d2020-07-10 11:42:03 +02004 - Copyright (c) 2017-2020 Linaro LTD
David Brownaac71112020-02-03 16:13:42 -07005 - Copyright (c) 2017-2019 JUUL Labs
Roland Mikhel206b9142023-02-23 15:28:52 +01006 - Copyright (c) 2019-2023 Arm Limited
David Brownaac71112020-02-03 16:13:42 -07007
8 - Original license:
9
10 - Licensed to the Apache Software Foundation (ASF) under one
11 - or more contributor license agreements. See the NOTICE file
12 - distributed with this work for additional information
13 - regarding copyright ownership. The ASF licenses this file
14 - to you under the Apache License, Version 2.0 (the
15 - "License"); you may not use this file except in compliance
16 - with the License. You may obtain a copy of the License at
17
18 - http://www.apache.org/licenses/LICENSE-2.0
19
20 - Unless required by applicable law or agreed to in writing,
21 - software distributed under the License is distributed on an
22 - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
23 - KIND, either express or implied. See the License for the
24 - specific language governing permissions and limitations
25 - under the License.
David Vinczeba3bd602019-06-17 16:01:43 +020026-->
27
Francesco Servidio482921f2021-10-20 15:42:59 +020028# Bootloader
David Brown17e20d12017-09-12 11:53:20 -060029
Fabio Utzigd37d8772019-12-03 10:32:18 -030030## [Summary](#summary)
Christopher Collins92ea77f2016-12-12 15:59:26 -080031
Francesco Servidio4ff0c182021-10-20 15:27:16 +020032MCUboot comprises two packages:
Christopher Collins92ea77f2016-12-12 15:59:26 -080033
David Brown17e20d12017-09-12 11:53:20 -060034* The bootutil library (boot/bootutil)
35* The boot application (each port has its own at boot/<port>)
Christopher Collins92ea77f2016-12-12 15:59:26 -080036
Francesco Servidio482921f2021-10-20 15:42:59 +020037The bootutil library performs most of the functions of a bootloader. In
Christopher Collins92ea77f2016-12-12 15:59:26 -080038particular, the piece that is missing is the final step of actually jumping to
39the main image. This last step is instead implemented by the boot application.
Francesco Servidio482921f2021-10-20 15:42:59 +020040Bootloader functionality is separated in this manner to enable unit testing of
41the bootloader. A library can be unit tested, but an application can't.
Christopher Collins92ea77f2016-12-12 15:59:26 -080042Therefore, functionality is delegated to the bootutil library when possible.
43
Fabio Utzigd37d8772019-12-03 10:32:18 -030044## [Limitations](#limitations)
Christopher Collins92ea77f2016-12-12 15:59:26 -080045
Francesco Servidio482921f2021-10-20 15:42:59 +020046The bootloader currently only supports images with the following
Christopher Collins92ea77f2016-12-12 15:59:26 -080047characteristics:
David Brown17e20d12017-09-12 11:53:20 -060048* Built to run from flash.
49* Built to run from a fixed location (i.e., not position-independent).
Christopher Collins92ea77f2016-12-12 15:59:26 -080050
Francesco Servidio5bc98322021-11-03 13:19:22 +010051## [Image format](#image-format)
Christopher Collins92ea77f2016-12-12 15:59:26 -080052
53The following definitions describe the image format.
54
David Brown17e20d12017-09-12 11:53:20 -060055``` c
Fabio Utzigea422c22017-09-11 11:02:47 -030056#define IMAGE_MAGIC 0x96f3b83d
Christopher Collins92ea77f2016-12-12 15:59:26 -080057
58#define IMAGE_HEADER_SIZE 32
59
60struct image_version {
61 uint8_t iv_major;
62 uint8_t iv_minor;
63 uint16_t iv_revision;
64 uint32_t iv_build_num;
65};
66
67/** Image header. All fields are in little endian byte order. */
68struct image_header {
69 uint32_t ih_magic;
Fabio Utzigea422c22017-09-11 11:02:47 -030070 uint32_t ih_load_addr;
David Vinczee32483f2019-06-13 10:46:24 +020071 uint16_t ih_hdr_size; /* Size of image header (bytes). */
72 uint16_t ih_protect_tlv_size; /* Size of protected TLV area (bytes). */
73 uint32_t ih_img_size; /* Does not include header. */
74 uint32_t ih_flags; /* IMAGE_F_[...]. */
Christopher Collins92ea77f2016-12-12 15:59:26 -080075 struct image_version ih_ver;
David Vinczee32483f2019-06-13 10:46:24 +020076 uint32_t _pad1;
Christopher Collins92ea77f2016-12-12 15:59:26 -080077};
78
Fabio Utzigfd140ec2019-09-12 14:37:48 -030079#define IMAGE_TLV_INFO_MAGIC 0x6907
80#define IMAGE_TLV_PROT_INFO_MAGIC 0x6908
81
Fabio Utzigea422c22017-09-11 11:02:47 -030082/** Image TLV header. All fields in little endian. */
83struct image_tlv_info {
84 uint16_t it_magic;
85 uint16_t it_tlv_tot; /* size of TLV area (including tlv_info header) */
86};
87
Christopher Collins92ea77f2016-12-12 15:59:26 -080088/** Image trailer TLV format. All fields in little endian. */
89struct image_tlv {
90 uint8_t it_type; /* IMAGE_TLV_[...]. */
91 uint8_t _pad;
Marti Bolivar49b29172017-08-04 14:50:51 -040092 uint16_t it_len; /* Data length (not including TLV header). */
Christopher Collins92ea77f2016-12-12 15:59:26 -080093};
94
95/*
96 * Image header flags.
97 */
Marti Bolivar7c057e92017-08-04 14:46:39 -040098#define IMAGE_F_PIC 0x00000001 /* Not supported. */
Salome Thirot0f641972021-05-14 11:19:55 +010099#define IMAGE_F_ENCRYPTED_AES128 0x00000004 /* Encrypted using AES128. */
100#define IMAGE_F_ENCRYPTED_AES256 0x00000008 /* Encrypted using AES256. */
Marti Bolivar7c057e92017-08-04 14:46:39 -0400101#define IMAGE_F_NON_BOOTABLE 0x00000010 /* Split image app. */
Fabio Utzigea422c22017-09-11 11:02:47 -0300102#define IMAGE_F_RAM_LOAD 0x00000020
Christopher Collins92ea77f2016-12-12 15:59:26 -0800103
104/*
105 * Image trailer TLV types.
106 */
Fabio Utzigea422c22017-09-11 11:02:47 -0300107#define IMAGE_TLV_KEYHASH 0x01 /* hash of the public key */
David Brown27648b82017-08-31 10:40:29 -0600108#define IMAGE_TLV_SHA256 0x10 /* SHA256 of image hdr and body */
Marko Kiiskila8dd56f32017-08-22 21:40:49 -0700109#define IMAGE_TLV_RSA2048_PSS 0x20 /* RSA2048 of hash output */
Roland Mikhel206b9142023-02-23 15:28:52 +0100110#define IMAGE_TLV_ECDSA224 0x21 /* ECDSA of hash output - Not supported anymore */
Roland Mikhel63d23462023-02-08 14:00:54 +0100111#define IMAGE_TLV_ECDSA256 0x22 /* ECDSA of hash output - Not supported anymore */
Fabio Utzig3501c012019-05-13 15:07:25 -0700112#define IMAGE_TLV_RSA3072_PSS 0x23 /* RSA3072 of hash output */
Fabio Utzig195411f2019-06-28 07:48:21 -0300113#define IMAGE_TLV_ED25519 0x24 /* ED25519 of hash output */
Roland Mikhel63d23462023-02-08 14:00:54 +0100114#define IMAGE_TLV_ECDSA_SIG 0x25 /* ECDSA of hash output */
David Vinczee32483f2019-06-13 10:46:24 +0200115#define IMAGE_TLV_ENC_RSA2048 0x30 /* Key encrypted with RSA-OAEP-2048 */
Salome Thirot0f641972021-05-14 11:19:55 +0100116#define IMAGE_TLV_ENC_KW 0x31 /* Key encrypted with AES-KW-128 or
117 256 */
Fabio Utzig5eaa5762020-04-02 13:30:43 -0300118#define IMAGE_TLV_ENC_EC256 0x32 /* Key encrypted with ECIES-P256 */
119#define IMAGE_TLV_ENC_X25519 0x33 /* Key encrypted with ECIES-X25519 */
David Vinczee32483f2019-06-13 10:46:24 +0200120#define IMAGE_TLV_DEPENDENCY 0x40 /* Image depends on other image */
David Vinczec3084132020-02-18 14:50:47 +0100121#define IMAGE_TLV_SEC_CNT 0x50 /* security counter */
David Brown17e20d12017-09-12 11:53:20 -0600122```
Christopher Collins92ea77f2016-12-12 15:59:26 -0800123
124Optional type-length-value records (TLVs) containing image metadata are placed
125after the end of the image.
126
David Vinczee32483f2019-06-13 10:46:24 +0200127The `ih_protect_tlv_size` field indicates the length of the protected TLV area.
Fabio Utzigfd140ec2019-09-12 14:37:48 -0300128If protected TLVs are present then a TLV info header with magic equal to
129`IMAGE_TLV_PROT_INFO_MAGIC` must be present and the protected TLVs (plus the
130info header itself) have to be included in the hash calculation. Otherwise the
131hash is only calculated over the image header and the image itself. In this
David Vinczee32483f2019-06-13 10:46:24 +0200132case the value of the `ih_protect_tlv_size` field is 0.
133
David Brown17e20d12017-09-12 11:53:20 -0600134The `ih_hdr_size` field indicates the length of the header, and therefore the
Christopher Collins92ea77f2016-12-12 15:59:26 -0800135offset of the image itself. This field provides for backwards compatibility in
136case of changes to the format of the image header.
137
Francesco Servidio5bc98322021-11-03 13:19:22 +0100138## [Flash map](#flash-map)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800139
Fabio Utzigac834962017-07-20 13:20:48 -0300140A device's flash is partitioned according to its _flash map_. At a high
Christopher Collins92ea77f2016-12-12 15:59:26 -0800141level, the flash map maps numeric IDs to _flash areas_. A flash area is a
142region of disk with the following properties:
David Brown17e20d12017-09-12 11:53:20 -06001431. An area can be fully erased without affecting any other areas.
1442. A write to one area does not restrict writes to other areas.
Christopher Collins92ea77f2016-12-12 15:59:26 -0800145
Francesco Servidio482921f2021-10-20 15:42:59 +0200146The bootloader uses the following flash area IDs:
David Vinczeb75c12a2019-03-22 14:58:33 +0100147```c
148/* Independent from multiple image boot */
David Vincze2d736ad2019-02-18 11:50:22 +0100149#define FLASH_AREA_BOOTLOADER 0
David Vinczeb75c12a2019-03-22 14:58:33 +0100150#define FLASH_AREA_IMAGE_SCRATCH 3
151```
152```c
Francesco Servidio482921f2021-10-20 15:42:59 +0200153/* If the bootloader is working with the first image */
David Vincze2d736ad2019-02-18 11:50:22 +0100154#define FLASH_AREA_IMAGE_PRIMARY 1
155#define FLASH_AREA_IMAGE_SECONDARY 2
David Vinczeb75c12a2019-03-22 14:58:33 +0100156```
157```c
Francesco Servidio482921f2021-10-20 15:42:59 +0200158/* If the bootloader is working with the second image */
David Vinczeb75c12a2019-03-22 14:58:33 +0100159#define FLASH_AREA_IMAGE_PRIMARY 5
160#define FLASH_AREA_IMAGE_SECONDARY 6
David Brown17e20d12017-09-12 11:53:20 -0600161```
Christopher Collins92ea77f2016-12-12 15:59:26 -0800162
Marti Bolivar4e64d562017-08-04 14:53:33 -0400163The bootloader area contains the bootloader image itself. The other areas are
David Vinczeb75c12a2019-03-22 14:58:33 +0100164described in subsequent sections. The flash could contain multiple executable
165images therefore the flash area IDs of primary and secondary areas are mapped
166based on the number of the active image (on which the bootloader is currently
167working).
Marti Bolivar4e64d562017-08-04 14:53:33 -0400168
Francesco Servidio5bc98322021-11-03 13:19:22 +0100169## [Image slots](#image-slots)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800170
David Vinczeb75c12a2019-03-22 14:58:33 +0100171A portion of the flash memory can be partitioned into multiple image areas, each
172contains two image slots: a primary slot and a secondary slot.
Francesco Servidio482921f2021-10-20 15:42:59 +0200173Normally, the bootloader will only run an image from the primary slot, so
David Vinczee574f2d2020-07-10 11:42:03 +0200174images must be built such that they can run from that fixed location in flash
Tamas Banfe031092020-09-10 17:32:39 +0200175(the exception to this is the [direct-xip](#direct-xip) and the
Francesco Servidio482921f2021-10-20 15:42:59 +0200176[ram-load](#ram-load) upgrade mode). If the bootloader needs to run the
Tamas Banfe031092020-09-10 17:32:39 +0200177image resident in the secondary slot, it must copy its contents into the primary
178slot before doing so, either by swapping the two images or by overwriting the
179contents of the primary slot. The bootloader supports either swap- or
180overwrite-based image upgrades, but must be configured at build time to choose
181one of these two strategies.
Christopher Collins92ea77f2016-12-12 15:59:26 -0800182
Andrzej Puzdrowski9abda322021-11-29 14:50:46 +0100183### [Swap using scratch](#image-swap-using-scratch)
184
185When swap-using-scratch algorithm is used, in addition to the slots of
186image areas, the bootloader requires a scratch area to allow for reliable
187image swapping. The scratch area must have a size
David Vinczeb75c12a2019-03-22 14:58:33 +0100188that is enough to store at least the largest sector that is going to be swapped.
189Many devices have small equally sized flash sectors, eg 4K, while others have
David Vincze2d736ad2019-02-18 11:50:22 +0100190variable sized sectors where the largest sectors might be 128K or 256K, so the
191scratch must be big enough to store that. The scratch is only ever used when
192swapping firmware, which means only when doing an upgrade. Given that, the main
193reason for using a larger size for the scratch is that flash wear will be more
194evenly distributed, because a single sector would be written twice the number of
195times than using two sectors, for example. To evaluate the ideal size of the
196scratch for your use case the following parameters are relevant:
Fabio Utziga722f5a2017-12-12 14:04:53 -0200197
198* the ratio of image size / scratch size
199* the number of erase cycles supported by the flash hardware
200
201The image size is used (instead of slot size) because only the slot's sectors
202that are actually used for storing the image are copied. The image/scratch ratio
203is the number of times the scratch will be erased on every upgrade. The number
204of erase cycles divided by the image/scratch ratio will give you the number of
205times an upgrade can be performed before the device goes out of spec.
206
207```
208num_upgrades = number_of_erase_cycles / (image_size / scratch_size)
209```
210
211Let's assume, for example, a device with 10000 erase cycles, an image size of
212150K and a scratch of 4K (usual minimum size of 4K sector devices). This would
213result in a total of:
214
215`10000 / (150 / 4) ~ 267`
216
217Increasing the scratch to 16K would give us:
218
219`10000 / (150 / 16) ~ 1067`
220
221There is no *best* ratio, as the right size is use-case dependent. Factors to
222consider include the number of times a device will be upgraded both in the field
David Vincze2d736ad2019-02-18 11:50:22 +0100223and during development, as well as any desired safety margin on the
224manufacturer's specified number of erase cycles. In general, using a ratio that
225allows hundreds to thousands of field upgrades in production is recommended.
Christopher Collins92ea77f2016-12-12 15:59:26 -0800226
Andrzej Puzdrowski9abda322021-11-29 14:50:46 +0100227swap-using scratch algorithm assumes that the primary and the secondary image
228slot areas sizes are equal.
229The maximum image size available for the application
Tamas Ban04efc2e2022-12-08 17:46:26 +0100230will be:
Andrzej Puzdrowski9abda322021-11-29 14:50:46 +0100231```
232maximum-image-size = image-slot-size - image-trailer-size
233```
234
Tamas Ban04efc2e2022-12-08 17:46:26 +0100235Where:
236 `image-slot-size` is the size of the image slot.
Andrzej Puzdrowski961a6102021-11-30 17:34:02 +0100237 `image-trailer-size` is the size of the image trailer.
Andrzej Puzdrowski9abda322021-11-29 14:50:46 +0100238
Andrzej Puzdrowski3c1e6d32021-11-25 09:39:33 +0100239### [Swap without using scratch](#image-swap-no-scratch)
240
241This algorithm is an alternative to the swap-using-scratch algorithm.
242It uses an additional sector in the primary slot to make swap possible.
243The algorithm works as follows:
244
Tamas Ban04efc2e2022-12-08 17:46:26 +0100245 1. Moves all sectors of the primary slot up by one sector.
246 Beginning from N=0:
Andrzej Puzdrowski3c1e6d32021-11-25 09:39:33 +0100247 2. Copies the N-th sector from the secondary slot to the N-th sector of the
248 primary slot.
249 3. Copies the (N+1)-th sector from the primary slot to the N-th sector of the
250 secondary slot.
251 4. Repeats steps 2. and 3. until all the slots' sectors are swapped.
252
253This algorithm is designed so that the higher sector of the primary slot is
254used only for allowing sectors to move up. Therefore the most
255memory-size-effective slot layout is when the primary slot is exactly one sector
256larger than the secondary slot, although same-sized slots are allowed as well.
257The algorithm is limited to support sectors of the same
258sector layout. All slot's sectors should be of the same size.
259
260When using this algorithm the maximum image size available for the application
Tamas Ban04efc2e2022-12-08 17:46:26 +0100261will be:
Andrzej Puzdrowski3c1e6d32021-11-25 09:39:33 +0100262```
263maximum-image-size = (N-1) * slot-sector-size - image-trailer-sectors-size
264```
265
Tamas Ban04efc2e2022-12-08 17:46:26 +0100266Where:
267 `N` is the number of sectors in the primary slot.
Andrzej Puzdrowski3c1e6d32021-11-25 09:39:33 +0100268 `image-trailer-sectors-size` is the size of the image trailer rounded up to
269 the total size of sectors its occupied. For instance if the image-trailer-size
270 is equal to 1056 B and the sector size is equal to 1024 B, then
271 `image-trailer-sectors-size` will be equal to 2048 B.
272
273The algorithm does two erase cycles on the primary slot and one on the secondary
274slot during each swap. Assuming that receiving a new image by the DFU
275application requires 1 erase cycle on the secondary slot, this should result in
276leveling the flash wear between the slots.
277
278The algorithm is enabled using the `MCUBOOT_SWAP_USING_MOVE` option.
279
David Vinczee574f2d2020-07-10 11:42:03 +0200280### [Equal slots (direct-xip)](#direct-xip)
281
282When the direct-xip mode is enabled the active image flag is "moved" between the
283slots during image upgrade and in contrast to the above, the bootloader can
284run an image directly from either the primary or the secondary slot (without
285having to move/copy it into the primary slot). Therefore the image update
286client, which downloads the new images must be aware, which slot contains the
287active image and which acts as a staging area and it is responsible for loading
288the proper images into the proper slot. All this requires that the images be
289built to be executed from the corresponding slot. At boot time the bootloader
290first looks for images in the slots and then inspects the version numbers in the
291image headers. It selects the newest image (with the highest version number) and
292then checks its validity (integrity check, signature verification etc.). If the
293image is invalid MCUboot erases its memory slot and starts to validate the other
294image. After a successful validation of the selected image the bootloader
295chain-loads it.
David Vincze505fba22020-10-22 13:53:29 +0200296
297An additional "revert" mechanism is also supported. For more information, please
298read the [corresponding section](#direct-xip-revert).
David Vinczee574f2d2020-07-10 11:42:03 +0200299Handling the primary and secondary slots as equals has its drawbacks. Since the
300images are not moved between the slots, the on-the-fly image
301encryption/decryption can't be supported (it only applies to storing the image
302in an external flash on the device, the transport of encrypted image data is
303still feasible).
304
305The overwrite and the direct-xip upgrade strategies are substantially simpler to
306implement than the image swapping strategy, especially since the bootloader must
307work properly even when it is reset during the middle of an image swap. For this
308reason, the rest of the document describes its behavior when configured to swap
309images during an upgrade.
Marti Bolivara91674f2017-08-04 14:56:08 -0400310
Francesco Servidio5bc98322021-11-03 13:19:22 +0100311### [RAM loading](#ram-load)
Tamas Banfe031092020-09-10 17:32:39 +0200312
313In ram-load mode the slots are equal. Like the direct-xip mode, this mode
314also selects the newest image by reading the image version numbers in the image
315headers. But instead of executing it in place, the newest image is copied to the
316RAM for execution. The load address, the location in RAM where the image is
317copied to, is stored in the image header. The ram-load upgrade mode can be
318useful when there is no internal flash in the SoC, but there is a big enough
319internal RAM to hold the images. Usually in this case the images are stored
320in an external storage device. Execution from external storage has some
321drawbacks (lower execution speed, image is exposed to attacks) therefore the
322image is always copied to the internal RAM before the authentication and
323execution. Ram-load mode requires the image to be built to be executed from
324the RAM address range instead of the storage device address range. If
325ram-load is enabled then platform must define the following parameters:
326
327```c
328#define IMAGE_EXECUTABLE_RAM_START <area_base_addr>
329#define IMAGE_EXECUTABLE_RAM_SIZE <area_size_in_bytes>
330```
331
Mark Horvathccaf7f82021-01-04 18:16:42 +0100332For multiple image load if multiple ram regions are used platform must define
333the `MULTIPLE_EXECUTABLE_RAM_REGIONS` flag instead and implement the following
334function:
335
336```c
337int boot_get_image_exec_ram_info(uint32_t image_id,
338 uint32_t *exec_ram_start,
339 uint32_t *exec_ram_size)
340```
341
Tamas Banfe031092020-09-10 17:32:39 +0200342When ram-load is enabled, the `--load-addr <addr>` option of the `imgtool`
343script must also be used when signing the images. This option set the `RAM_LOAD`
344flag in the image header which indicates that the image should be loaded to the
345RAM and also set the load address in the image header.
346
Hugo L'Hostisdb543e52021-03-09 18:00:31 +0000347When the encryption option is enabled (`MCUBOOT_ENC_IMAGES`) along with ram-load
348the image is checked for encryption. If the image is not encrypted, RAM loading
349happens as described above. If the image is encrypted, it is copied in RAM at
350the provided address and then decrypted. Finally, the decrypted image is
351authenticated in RAM and executed.
Tamas Banfe031092020-09-10 17:32:39 +0200352
Francesco Servidio5bc98322021-11-03 13:19:22 +0100353## [Boot swap types](#boot-swap-types)
Christopher Collinsfd7eb5c2016-12-21 13:46:08 -0800354
Marti Bolivar048d8d82017-08-04 17:14:24 -0400355When the device first boots under normal circumstances, there is an up-to-date
Francesco Servidio4ff0c182021-10-20 15:27:16 +0200356firmware image in each primary slot, which MCUboot can validate and then
David Vincze2d736ad2019-02-18 11:50:22 +0100357chain-load. In this case, no image swaps are necessary. During device upgrades,
David Vinczeba3bd602019-06-17 16:01:43 +0200358however, new candidate image(s) is present in the secondary slot(s), which
Francesco Servidio4ff0c182021-10-20 15:27:16 +0200359MCUboot must swap into the primary slot(s) before booting as discussed above.
Christopher Collinsfd7eb5c2016-12-21 13:46:08 -0800360
Marti Bolivar048d8d82017-08-04 17:14:24 -0400361Upgrading an old image with a new one by swapping can be a two-step process. In
Francesco Servidio4ff0c182021-10-20 15:27:16 +0200362this process, MCUboot performs a "test" swap of image data in flash and boots
David Vinczeba3bd602019-06-17 16:01:43 +0200363the new image or it will be executed during operation. The new image can then
Francesco Servidio4ff0c182021-10-20 15:27:16 +0200364update the contents of flash at runtime to mark itself "OK", and MCUboot will
David Vinczeba3bd602019-06-17 16:01:43 +0200365then still choose to run it during the next boot. When this happens, the swap is
Francesco Servidio4ff0c182021-10-20 15:27:16 +0200366made "permanent". If this doesn't happen, MCUboot will perform a "revert" swap
David Vinczeba3bd602019-06-17 16:01:43 +0200367during the next boot by swapping the image(s) back into its original location(s)
368, and attempting to boot the old image(s).
Christopher Collinsfd7eb5c2016-12-21 13:46:08 -0800369
Marti Bolivar048d8d82017-08-04 17:14:24 -0400370Depending on the use case, the first swap can also be made permanent directly.
Francesco Servidio4ff0c182021-10-20 15:27:16 +0200371In this case, MCUboot will never attempt to revert the images on the next reset.
Christopher Collinsfd7eb5c2016-12-21 13:46:08 -0800372
Marti Bolivar048d8d82017-08-04 17:14:24 -0400373Test swaps are supported to provide a rollback mechanism to prevent devices
374from becoming "bricked" by bad firmware. If the device crashes immediately
Francesco Servidio4ff0c182021-10-20 15:27:16 +0200375upon booting a new (bad) image, MCUboot will revert to the old (working) image
Marti Bolivar048d8d82017-08-04 17:14:24 -0400376at the next device reset, rather than booting the bad image again. This allows
377device firmware to make test swaps permanent only after performing a self-test
378routine.
Christopher Collinsfd7eb5c2016-12-21 13:46:08 -0800379
Francesco Servidio4ff0c182021-10-20 15:27:16 +0200380On startup, MCUboot inspects the contents of flash to decide for each images
David Vinczeba3bd602019-06-17 16:01:43 +0200381which of these "swap types" to perform; this decision determines how it
382proceeds.
Christopher Collinsfd7eb5c2016-12-21 13:46:08 -0800383
Marti Bolivar048d8d82017-08-04 17:14:24 -0400384The possible swap types, and their meanings, are:
Christopher Collinsfd7eb5c2016-12-21 13:46:08 -0800385
David Brown17e20d12017-09-12 11:53:20 -0600386- `BOOT_SWAP_TYPE_NONE`: The "usual" or "no upgrade" case; attempt to boot the
David Vincze2d736ad2019-02-18 11:50:22 +0100387 contents of the primary slot.
Christopher Collinsfd7eb5c2016-12-21 13:46:08 -0800388
David Vincze2d736ad2019-02-18 11:50:22 +0100389- `BOOT_SWAP_TYPE_TEST`: Boot the contents of the secondary slot by swapping
390 images. Unless the swap is made permanent, revert back on the next boot.
Christopher Collinsfd7eb5c2016-12-21 13:46:08 -0800391
David Brown17e20d12017-09-12 11:53:20 -0600392- `BOOT_SWAP_TYPE_PERM`: Permanently swap images, and boot the upgraded image
Marti Bolivar048d8d82017-08-04 17:14:24 -0400393 firmware.
Christopher Collinsfd7eb5c2016-12-21 13:46:08 -0800394
David Vincze2d736ad2019-02-18 11:50:22 +0100395- `BOOT_SWAP_TYPE_REVERT`: A previous test swap was not made permanent;
396 swap back to the old image whose data are now in the secondary slot. If the
397 old image marks itself "OK" when it boots, the next boot will have swap type
398 `BOOT_SWAP_TYPE_NONE`.
Christopher Collinsfd7eb5c2016-12-21 13:46:08 -0800399
David Brown17e20d12017-09-12 11:53:20 -0600400- `BOOT_SWAP_TYPE_FAIL`: Swap failed because image to be run is not valid.
Marti Bolivar048d8d82017-08-04 17:14:24 -0400401
David Brown17e20d12017-09-12 11:53:20 -0600402- `BOOT_SWAP_TYPE_PANIC`: Swapping encountered an unrecoverable error.
Marti Bolivar048d8d82017-08-04 17:14:24 -0400403
404The "swap type" is a high-level representation of the outcome of the
Francesco Servidio4ff0c182021-10-20 15:27:16 +0200405boot. Subsequent sections describe how MCUboot determines the swap type from
Marti Bolivar048d8d82017-08-04 17:14:24 -0400406the bit-level contents of flash.
Christopher Collinsfd7eb5c2016-12-21 13:46:08 -0800407
David Vincze505fba22020-10-22 13:53:29 +0200408### [Revert mechanism in direct-xip mode](#direct-xip-revert)
409
410The direct-xip mode also supports a "revert" mechanism which is the equivalent
David Vincze1c456242021-06-29 15:25:24 +0200411of the swap mode's "revert" swap. When the direct-xip mode is selected it can be
412enabled with the MCUBOOT_DIRECT_XIP_REVERT config option and an image trailer
413must also be added to the signed images (the "--pad" option of the `imgtool`
414script must be used). For more information on this please read the
415[Image Trailer](#image-trailer) section and the [imgtool](imgtool.md)
416documentation. Making the images permanent (marking them as confirmed in
417advance) is also supported just like in swap mode. The individual steps of the
418direct-xip mode's "revert" mechanism are the following:
David Vincze505fba22020-10-22 13:53:29 +0200419
4201. Select the slot which holds the newest potential image.
4212. Was the image previously selected to run (during a previous boot)?
422 + Yes: Did the image mark itself "OK" (was the self-test successful)?
423 + Yes.
424 - Proceed to step 3.
425 + No.
426 - Erase the image from the slot to prevent it from being selected
427 again during the next boot.
428 - Return to step 1 (the bootloader will attempt to select and
429 possibly boot the previous image if there is one).
430 + No.
431 - Mark the image as "selected" (set the copy_done flag in the trailer).
432 - Proceed to step 3.
4333. Proceed to image validation ...
434
Francesco Servidio5bc98322021-11-03 13:19:22 +0100435## [Image trailer](#image-trailer)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800436
Fabio Utzig86fe4b22017-07-28 18:56:29 -0300437For the bootloader to be able to determine the current state and what actions
Marti Bolivar42818032017-08-04 15:45:01 -0400438should be taken during the current boot operation, it uses metadata stored in
439the image flash areas. While swapping, some of this metadata is temporarily
440copied into and out of the scratch area.
441
442This metadata is located at the end of the image flash areas, and is called an
443image trailer. An image trailer has the following structure:
Christopher Collins92ea77f2016-12-12 15:59:26 -0800444
David Brown17e20d12017-09-12 11:53:20 -0600445```
Christopher Collins92ea77f2016-12-12 15:59:26 -0800446 0 1 2 3
447 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
448 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Christopher Collins92ea77f2016-12-12 15:59:26 -0800449 ~ ~
Fabio Utzig2c05f1b2018-04-04 10:35:17 -0300450 ~ Swap status (BOOT_MAX_IMG_SECTORS * min-write-size * 3) ~
Christopher Collins92ea77f2016-12-12 15:59:26 -0800451 ~ ~
452 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Christopher Collinsa1c12042019-05-23 14:00:28 -0700453 | Encryption key 0 (16 octets) [*] |
454 | |
Christopher Collins92ea77f2016-12-12 15:59:26 -0800455 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Gustavo Henrique Nihei41f123c2021-11-22 18:45:48 -0300456 | 0xff padding as needed |
457 | (BOOT_MAX_ALIGN minus 16 octets from Encryption key 0) [*] |
458 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Christopher Collinsa1c12042019-05-23 14:00:28 -0700459 | Encryption key 1 (16 octets) [*] |
460 | |
Fabio Utzig5bd4e582017-07-20 08:55:38 -0300461 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Gustavo Henrique Nihei41f123c2021-11-22 18:45:48 -0300462 | 0xff padding as needed |
463 | (BOOT_MAX_ALIGN minus 16 octets from Encryption key 1) [*] |
464 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Christopher Collinsa1c12042019-05-23 14:00:28 -0700465 | Swap size (4 octets) |
Fabio Utzigea422c22017-09-11 11:02:47 -0300466 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Gustavo Henrique Nihei41f123c2021-11-22 18:45:48 -0300467 | 0xff padding as needed |
468 | (BOOT_MAX_ALIGN minus 4 octets from Swap size) |
Fabio Utzigea422c22017-09-11 11:02:47 -0300469 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Gustavo Henrique Nihei41f123c2021-11-22 18:45:48 -0300470 | Swap info | 0xff padding (BOOT_MAX_ALIGN minus 1 octet) |
Christopher Collinsa1c12042019-05-23 14:00:28 -0700471 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Gustavo Henrique Nihei41f123c2021-11-22 18:45:48 -0300472 | Copy done | 0xff padding (BOOT_MAX_ALIGN minus 1 octet) |
473 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
474 | Image OK | 0xff padding (BOOT_MAX_ALIGN minus 1 octet) |
475 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
476 | 0xff padding as needed |
477 | (BOOT_MAX_ALIGN minus 16 octets from MAGIC) |
Christopher Collinsa1c12042019-05-23 14:00:28 -0700478 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
479 | MAGIC (16 octets) |
480 | |
Christopher Collins92ea77f2016-12-12 15:59:26 -0800481 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
David Brown17e20d12017-09-12 11:53:20 -0600482```
Christopher Collins92ea77f2016-12-12 15:59:26 -0800483
Christopher Collinsa1c12042019-05-23 14:00:28 -0700484[*]: Only present if the encryption option is enabled (`MCUBOOT_ENC_IMAGES`).
485
Marti Bolivar42818032017-08-04 15:45:01 -0400486The offset immediately following such a record represents the start of the next
487flash area.
Christopher Collins92ea77f2016-12-12 15:59:26 -0800488
Francesco Servidio2fe449d2021-10-21 12:38:36 +0200489---
490***Note***
491
492*"min-write-size" is a property of the flash hardware. If the hardware*
493*allows individual bytes to be written at arbitrary addresses, then*
494*min-write-size is 1. If the hardware only allows writes at even addresses,*
495*then min-write-size is 2, and so on.*
496
497---
Christopher Collins92ea77f2016-12-12 15:59:26 -0800498
Marti Bolivar1dcb6852017-08-04 15:59:32 -0400499An image trailer contains the following fields:
Christopher Collins92ea77f2016-12-12 15:59:26 -0800500
Marti Bolivar1dcb6852017-08-04 15:59:32 -04005011. Swap status: A series of records which records the progress of an image
David Vincze2d736ad2019-02-18 11:50:22 +0100502 swap. To swap entire images, data are swapped between the two image areas
503 one or more sectors at a time, like this:
Marti Bolivar1dcb6852017-08-04 15:59:32 -0400504
David Vincze2d736ad2019-02-18 11:50:22 +0100505 - sector data in the primary slot is copied into scratch, then erased
506 - sector data in the secondary slot is copied into the primary slot,
507 then erased
508 - sector data in scratch is copied into the secondary slot
Marti Bolivar1dcb6852017-08-04 15:59:32 -0400509
510As it swaps images, the bootloader updates the swap status field in a way that
511allows it to compute how far this swap operation has progressed for each
512sector. The swap status field can thus used to resume a swap operation if the
513bootloader is halted while a swap operation is ongoing and later reset. The
David Vincze2d736ad2019-02-18 11:50:22 +0100514`BOOT_MAX_IMG_SECTORS` value is the configurable maximum number of sectors
Francesco Servidio4ff0c182021-10-20 15:27:16 +0200515MCUboot supports for each image; its value defaults to 128, but allows for
David Vincze2d736ad2019-02-18 11:50:22 +0100516either decreasing this size, to limit RAM usage, or to increase it in devices
517that have massive amounts of Flash or very small sized sectors and thus require
518a bigger configuration to allow for the handling of all slot's sectors.
iysheng506a16f2021-08-26 06:13:11 +0800519The factor of min-write-size is due to the behavior of flash hardware. The factor
David Vincze2d736ad2019-02-18 11:50:22 +0100520of 3 is explained below.
Fabio Utzig5bd4e582017-07-20 08:55:38 -0300521
Christopher Collinsa1c12042019-05-23 14:00:28 -07005222. Encryption keys: key-encrypting keys (KEKs). These keys are needed for
523 image encryption and decryption. See the
524 [encrypted images](encrypted_images.md) document for more information.
525
5263. Swap size: When beginning a new swap operation, the total size that needs
Håkon Øye Amundsencbf30472019-07-24 08:34:03 +0000527 to be swapped (based on the slot with largest image + TLVs) is written to
David Vincze2d736ad2019-02-18 11:50:22 +0100528 this location for easier recovery in case of a reset while performing the
529 swap.
Fabio Utzigea422c22017-09-11 11:02:47 -0300530
Håkon Øye Amundsencbf30472019-07-24 08:34:03 +00005314. Swap info: A single byte which encodes the following information:
David Vinczee2453472019-06-17 12:31:59 +0200532 - Swap type: Stored in bits 0-3. Indicating the type of swap operation in
Francesco Servidio4ff0c182021-10-20 15:27:16 +0200533 progress. When MCUboot resumes an interrupted swap, it uses this field to
David Vinczee2453472019-06-17 12:31:59 +0200534 determine the type of operation to perform. This field contains one of the
535 following values in the table below.
536 - Image number: Stored in bits 4-7. It has always 0 value at single image
537 boot. In case of multi image boot it indicates, which image was swapped when
538 interrupt happened. The same scratch area is used during in case of all
539 image swap operation. Therefore this field is used to determine which image
540 the trailer belongs to if boot status is found on scratch area when the swap
541 operation is resumed.
Christopher Collinsa1c12042019-05-23 14:00:28 -0700542
543| Name | Value |
544| ------------------------- | ----- |
545| `BOOT_SWAP_TYPE_TEST` | 2 |
546| `BOOT_SWAP_TYPE_PERM` | 3 |
547| `BOOT_SWAP_TYPE_REVERT` | 4 |
548
549
5505. Copy done: A single byte indicating whether the image in this slot is
David Brown17e20d12017-09-12 11:53:20 -0600551 complete (0x01=done; 0xff=not done).
Fabio Utzig5bd4e582017-07-20 08:55:38 -0300552
Christopher Collinsa1c12042019-05-23 14:00:28 -07005536. Image OK: A single byte indicating whether the image in this slot has been
David Brown17e20d12017-09-12 11:53:20 -0600554 confirmed as good by the user (0x01=confirmed; 0xff=not confirmed).
Fabio Utzig5bd4e582017-07-20 08:55:38 -0300555
Gustavo Henrique Nihei41f123c2021-11-22 18:45:48 -03005567. MAGIC: A 16-byte field identifying the image trailer layout. It may assume
557 distinct values depending on the maximum supported write alignment
558 (`BOOT_MAX_ALIGN`) of the image, as defined by the following construct:
Christopher Collins92ea77f2016-12-12 15:59:26 -0800559
David Brown17e20d12017-09-12 11:53:20 -0600560``` c
Gustavo Henrique Nihei41f123c2021-11-22 18:45:48 -0300561union boot_img_magic_t
562{
563 struct {
564 uint16_t align;
565 uint8_t magic[14];
Christopher Collins92ea77f2016-12-12 15:59:26 -0800566 };
Gustavo Henrique Nihei41f123c2021-11-22 18:45:48 -0300567 uint8_t val[16];
568};
David Brown17e20d12017-09-12 11:53:20 -0600569```
Gustavo Henrique Nihei41f123c2021-11-22 18:45:48 -0300570 If `BOOT_MAX_ALIGN` is **8 bytes**, then MAGIC contains the following 16 bytes:
571
572``` c
573const union boot_img_magic_t boot_img_magic = {
574 .val = {
575 0x77, 0xc2, 0x95, 0xf3,
576 0x60, 0xd2, 0xef, 0x7f,
577 0x35, 0x52, 0x50, 0x0f,
578 0x2c, 0xb6, 0x79, 0x80
579 }
580};
581```
582
583 In case `BOOT_MAX_ALIGN` is defined to any value different than **8**, then the maximum
584 supported write alignment value is encoded in the MAGIC field, followed by a fixed
585 14-byte pattern:
586
587``` c
588const union boot_img_magic_t boot_img_magic = {
589 .align = BOOT_MAX_ALIGN,
590 .magic = {
591 0x2d, 0xe1,
592 0x5d, 0x29, 0x41, 0x0b,
593 0x8d, 0x77, 0x67, 0x9c,
594 0x11, 0x0f, 0x1f, 0x8a
595 }
596};
597```
598
Andrzej Puzdrowskicd35fef2021-11-25 16:15:08 +0100599---
600***Note***
601Be aware that the image trailers make the ending area of the image slot
602unavailable for carrying the image data. In particular, the swap status size
603could be huge. For example, for 128 slot sectors with a 4-byte alignment,
604it would become 1536 B.
605
606---
Christopher Collins92ea77f2016-12-12 15:59:26 -0800607
Francesco Servidio5bc98322021-11-03 13:19:22 +0100608## [Image trailers](#image-trailers)
Fabio Utzig86fe4b22017-07-28 18:56:29 -0300609
Francesco Servidio482921f2021-10-20 15:42:59 +0200610At startup, the bootloader determines the boot swap type by inspecting the
Marti Bolivar048d8d82017-08-04 17:14:24 -0400611image trailers. When using the term "image trailers" what is meant is the
612aggregate information provided by both image slot's trailers.
Fabio Utzig86fe4b22017-07-28 18:56:29 -0300613
Fabio Utzigd37d8772019-12-03 10:32:18 -0300614### [New swaps (non-resumes)](#new-swaps-non-resumes)
Christopher Collinsa1c12042019-05-23 14:00:28 -0700615
Francesco Servidio4ff0c182021-10-20 15:27:16 +0200616For new swaps, MCUboot must inspect a collection of fields to determine which
Christopher Collinsa1c12042019-05-23 14:00:28 -0700617swap operation to perform.
618
David Vincze2d736ad2019-02-18 11:50:22 +0100619The image trailers records are structured around the limitations imposed by
620flash hardware. As a consequence, they do not have a very intuitive design, and
621it is difficult to get a sense of the state of the device just by looking at the
Marti Bolivar048d8d82017-08-04 17:14:24 -0400622image trailers. It is better to map all the possible trailer states to the swap
623types described above via a set of tables. These tables are reproduced below.
Fabio Utzig86fe4b22017-07-28 18:56:29 -0300624
Francesco Servidio2fe449d2021-10-21 12:38:36 +0200625---
626***Note***
627
628*An important caveat about the tables described below is that they must*
629*be evaluated in the order presented here. Lower state numbers must have a*
630*higher priority when testing the image trailers.*
631
632---
Christopher Collins92ea77f2016-12-12 15:59:26 -0800633
David Brown17e20d12017-09-12 11:53:20 -0600634```
Christopher Collins92ea77f2016-12-12 15:59:26 -0800635 State I
David Vincze2d736ad2019-02-18 11:50:22 +0100636 | primary slot | secondary slot |
637 -----------------+--------------+----------------|
638 magic | Any | Good |
639 image-ok | Any | Unset |
640 copy-done | Any | Any |
641 -----------------+--------------+----------------'
642 result: BOOT_SWAP_TYPE_TEST |
643 -------------------------------------------------'
Fabio Utzig5bd4e582017-07-20 08:55:38 -0300644
Christopher Collins92ea77f2016-12-12 15:59:26 -0800645
Fabio Utzig86fe4b22017-07-28 18:56:29 -0300646 State II
David Vincze2d736ad2019-02-18 11:50:22 +0100647 | primary slot | secondary slot |
648 -----------------+--------------+----------------|
649 magic | Any | Good |
650 image-ok | Any | 0x01 |
651 copy-done | Any | Any |
652 -----------------+--------------+----------------'
653 result: BOOT_SWAP_TYPE_PERM |
654 -------------------------------------------------'
Fabio Utzig5bd4e582017-07-20 08:55:38 -0300655
Christopher Collinsfd7eb5c2016-12-21 13:46:08 -0800656
Fabio Utzig86fe4b22017-07-28 18:56:29 -0300657 State III
David Vincze2d736ad2019-02-18 11:50:22 +0100658 | primary slot | secondary slot |
659 -----------------+--------------+----------------|
660 magic | Good | Unset |
661 image-ok | 0xff | Any |
662 copy-done | 0x01 | Any |
663 -----------------+--------------+----------------'
664 result: BOOT_SWAP_TYPE_REVERT |
665 -------------------------------------------------'
David Brown17e20d12017-09-12 11:53:20 -0600666```
Christopher Collins92ea77f2016-12-12 15:59:26 -0800667
Francesco Servidio4ff0c182021-10-20 15:27:16 +0200668Any of the above three states results in MCUboot attempting to swap images.
Christopher Collins92ea77f2016-12-12 15:59:26 -0800669
Francesco Servidio4ff0c182021-10-20 15:27:16 +0200670Otherwise, MCUboot does not attempt to swap images, resulting in one of the
Marti Bolivar048d8d82017-08-04 17:14:24 -0400671other three swap types, as illustrated by State IV.
Fabio Utzig86fe4b22017-07-28 18:56:29 -0300672
David Brown17e20d12017-09-12 11:53:20 -0600673```
Fabio Utzig86fe4b22017-07-28 18:56:29 -0300674 State IV
David Vincze2d736ad2019-02-18 11:50:22 +0100675 | primary slot | secondary slot |
676 -----------------+--------------+----------------|
677 magic | Any | Any |
678 image-ok | Any | Any |
679 copy-done | Any | Any |
680 -----------------+--------------+----------------'
681 result: BOOT_SWAP_TYPE_NONE, |
682 BOOT_SWAP_TYPE_FAIL, or |
683 BOOT_SWAP_TYPE_PANIC |
684 -------------------------------------------------'
David Brown17e20d12017-09-12 11:53:20 -0600685```
Christopher Collins92ea77f2016-12-12 15:59:26 -0800686
Francesco Servidio4ff0c182021-10-20 15:27:16 +0200687In State IV, when no errors occur, MCUboot will attempt to boot the contents of
David Vincze2d736ad2019-02-18 11:50:22 +0100688the primary slot directly, and the result is `BOOT_SWAP_TYPE_NONE`. If the image
689in the primary slot is not valid, the result is `BOOT_SWAP_TYPE_FAIL`. If a
690fatal error occurs during boot, the result is `BOOT_SWAP_TYPE_PANIC`. If the
Francesco Servidio4ff0c182021-10-20 15:27:16 +0200691result is either `BOOT_SWAP_TYPE_FAIL` or `BOOT_SWAP_TYPE_PANIC`, MCUboot hangs
David Vincze2d736ad2019-02-18 11:50:22 +0100692rather than booting an invalid or compromised image.
Fabio Utzig86fe4b22017-07-28 18:56:29 -0300693
Francesco Servidio2fe449d2021-10-21 12:38:36 +0200694---
695***Note***
696
697*An important caveat to the above is the result when a swap is requested*
698*and the image in the secondary slot fails to validate, due to a hashing or*
699*signing error. This state behaves as State IV with the extra action of*
700*marking the image in the primary slot as "OK", to prevent further attempts*
701*to swap.*
702
703---
Fabio Utzig86fe4b22017-07-28 18:56:29 -0300704
Fabio Utzigd37d8772019-12-03 10:32:18 -0300705### [Resumed swaps](#resumed-swaps)
Christopher Collinsa1c12042019-05-23 14:00:28 -0700706
Francesco Servidio4ff0c182021-10-20 15:27:16 +0200707If MCUboot determines that it is resuming an interrupted swap (i.e., a reset
Christopher Collinsa1c12042019-05-23 14:00:28 -0700708occurred mid-swap), it fully determines the operation to resume by reading the
David Vinczee2453472019-06-17 12:31:59 +0200709`swap info` field from the active trailer and extracting the swap type from bits
7100-3. The set of tables in the previous section are not necessary in the resume
711case.
Christopher Collinsa1c12042019-05-23 14:00:28 -0700712
Francesco Servidio5bc98322021-11-03 13:19:22 +0100713## [High-level operation](#high-level-operation)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800714
Francesco Servidio482921f2021-10-20 15:42:59 +0200715With the terms defined, we can now explore the bootloader's operation. First,
Christopher Collins92ea77f2016-12-12 15:59:26 -0800716a high-level overview of the boot process is presented. Then, the following
717sections describe each step of the process in more detail.
718
719Procedure:
720
David Brown17e20d12017-09-12 11:53:20 -06007211. Inspect swap status region; is an interrupted swap being resumed?
Fabio Utzig75b34412019-09-06 08:30:43 -0300722 + Yes: Complete the partial swap operation; skip to step 3.
723 + No: Proceed to step 2.
Christopher Collins92ea77f2016-12-12 15:59:26 -0800724
David Brown17e20d12017-09-12 11:53:20 -06007252. Inspect image trailers; is a swap requested?
Fabio Utzig75b34412019-09-06 08:30:43 -0300726 + Yes:
727 1. Is the requested image valid (integrity and security check)?
728 + Yes.
729 a. Perform swap operation.
730 b. Persist completion of swap procedure to image trailers.
731 c. Proceed to step 3.
732 + No.
733 a. Erase invalid image.
734 b. Persist failure of swap procedure to image trailers.
735 c. Proceed to step 3.
736
737 + No: Proceed to step 3.
Christopher Collins92ea77f2016-12-12 15:59:26 -0800738
David Vincze2d736ad2019-02-18 11:50:22 +01007393. Boot into image in primary slot.
Christopher Collins92ea77f2016-12-12 15:59:26 -0800740
Francesco Servidio5bc98322021-11-03 13:19:22 +0100741### [Multiple image boot](#multiple-image-boot)
David Vinczeba3bd602019-06-17 16:01:43 +0200742
Francesco Servidio482921f2021-10-20 15:42:59 +0200743When the flash contains multiple executable images the bootloader's operation
David Vinczeba3bd602019-06-17 16:01:43 +0200744is a bit more complex but similar to the previously described procedure with
745one image. Every image can be updated independently therefore the flash is
746partitioned further to arrange two slots for each image.
747```
748+--------------------+
Francesco Servidio4ff0c182021-10-20 15:27:16 +0200749| MCUboot |
David Vinczeba3bd602019-06-17 16:01:43 +0200750+--------------------+
751 ~~~~~ <- memory might be not contiguous
752+--------------------+
753| Image 0 |
754| primary slot |
755+--------------------+
756| Image 0 |
757| secondary slot |
758+--------------------+
759 ~~~~~ <- memory might be not contiguous
760+--------------------+
761| Image N |
762| primary slot |
763+--------------------+
764| Image N |
765| secondary slot |
766+--------------------+
767| Scratch |
768+--------------------+
769```
Francesco Servidio4ff0c182021-10-20 15:27:16 +0200770MCUboot is also capable of handling dependencies between images. For example
David Vinczee32483f2019-06-13 10:46:24 +0200771if an image needs to be reverted it might be necessary to revert another one too
772(e.g. due to API incompatibilities) or simply to prevent from being updated
773because of an unsatisfied dependency. Therefore all aborted swaps have to be
774completed and all the swap types have to be determined for each image before
775the dependency checks. Dependency handling is described in more detail in a
776following section. The multiple image boot procedure is organized in loops which
777iterate over all the firmware images. The high-level overview of the boot
778process is presented below.
David Vinczeba3bd602019-06-17 16:01:43 +0200779
Martí Bolívara6a0e0e2019-08-08 07:12:54 -0700780+ Loop 1. Iterate over all images
David Vinczeba3bd602019-06-17 16:01:43 +0200781 1. Inspect swap status region of current image; is an interrupted swap being
782 resumed?
783 + Yes:
784 + Review the validity of previously determined swap types
785 of other images.
786 + Complete the partial swap operation.
787 + Mark the swap type as `None`.
788 + Skip to next image.
789 + No: Proceed to step 2.
790
791 2. Inspect image trailers in the primary and secondary slot; is an image
792 swap requested?
793 + Yes: Review the validity of previously determined swap types of other
794 images. Is the requested image valid (integrity and security
795 check)?
796 + Yes:
797 + Set the previously determined swap type for the current image.
798 + Skip to next image.
799 + No:
800 + Erase invalid image.
801 + Persist failure of swap procedure to image trailers.
802 + Mark the swap type as `Fail`.
803 + Skip to next image.
804 + No:
805 + Mark the swap type as `None`.
806 + Skip to next image.
807
Martí Bolívara6a0e0e2019-08-08 07:12:54 -0700808+ Loop 2. Iterate over all images
David Vinczee32483f2019-06-13 10:46:24 +0200809 1. Does the current image depend on other image(s)?
810 + Yes: Are all the image dependencies satisfied?
811 + Yes: Skip to next image.
812 + No:
813 + Modify swap type depending on what the previous type was.
814 + Restart dependency check from the first image.
815 + No: Skip to next image.
David Vinczeba3bd602019-06-17 16:01:43 +0200816
Martí Bolívara6a0e0e2019-08-08 07:12:54 -0700817+ Loop 3. Iterate over all images
David Vinczeba3bd602019-06-17 16:01:43 +0200818 1. Is an image swap requested?
819 + Yes:
820 + Perform image update operation.
821 + Persist completion of swap procedure to image trailers.
822 + Skip to next image.
823 + No: Skip to next image.
824
Martí Bolívara6a0e0e2019-08-08 07:12:54 -0700825+ Loop 4. Iterate over all images
David Vinczeba3bd602019-06-17 16:01:43 +0200826 1. Validate image in the primary slot (integrity and security check) or
827 at least do a basic sanity check to avoid booting into an empty flash
828 area.
829
830+ Boot into image in the primary slot of the 0th image position\
831 (other image in the boot chain is started by another image).
832
Francesco Servidio5bc98322021-11-03 13:19:22 +0100833### [Multiple image boot for RAM loading and direct-xip](#multiple-image-boot-for-ram-loading-and-direct-xip)
Mark Horvathccaf7f82021-01-04 18:16:42 +0100834
Francesco Servidio482921f2021-10-20 15:42:59 +0200835The operation of the bootloader is different when the ram-load or the
Mark Horvathccaf7f82021-01-04 18:16:42 +0100836direct-xip strategy is chosen. The flash map is very similar to the swap
837strategy but there is no need for Scratch area.
838
839+ Loop 1. Until all images are loaded and all dependencies are satisfied
840 1. Subloop 1. Iterate over all images
841 + Does any of the slots contain an image?
842 + Yes:
843 + Choose the newer image.
844 + Copy it to RAM in case of ram-load strategy.
845 + Validate the image (integrity and security check).
846 + If validation fails delete the image from flash and try the other
847 slot. (Image must be deleted from RAM too in case of ram-load
848 strategy.)
849 + No: Return with failure.
850
851 2. Subloop 2. Iterate over all images
852 + Does the current image depend on other image(s)?
853 + Yes: Are all the image dependencies satisfied?
854 + Yes: Skip to next image.
855 + No:
856 + Delete the image from RAM in case of ram-load strategy, but
857 do not delete it from flash.
858 + Try to load the image from the other slot.
859 + Restart dependency check from the first image.
860 + No: Skip to next image.
861
862+ Loop 2. Iterate over all images
863 + Increase the security counter if needed.
864 + Do the measured boot and the data sharing if needed.
865
866+ Boot the loaded slot of image 0.
867
Francesco Servidio5bc98322021-11-03 13:19:22 +0100868## [Image swapping](#image-swapping)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800869
Francesco Servidio482921f2021-10-20 15:42:59 +0200870The bootloader swaps the contents of the two image slots for two reasons:
Fabio Utzig75b34412019-09-06 08:30:43 -0300871
872 * User has issued a "set pending" operation; the image in the secondary slot
Håkon Øye Amundsen11d91c32020-03-04 08:49:47 +0000873 should be run once (state I) or repeatedly (state II), depending on
Fabio Utzig75b34412019-09-06 08:30:43 -0300874 whether a permanent swap was specified.
Francesco Servidio482921f2021-10-20 15:42:59 +0200875 * Test image rebooted without being confirmed; the bootloader should
Håkon Øye Amundsen11d91c32020-03-04 08:49:47 +0000876 revert to the original image currently in the secondary slot (state III).
Christopher Collins92ea77f2016-12-12 15:59:26 -0800877
Fabio Utzig86fe4b22017-07-28 18:56:29 -0300878If the image trailers indicates that the image in the secondary slot should be
Francesco Servidio482921f2021-10-20 15:42:59 +0200879run, the bootloader needs to copy it to the primary slot. The image currently
Christopher Collins92ea77f2016-12-12 15:59:26 -0800880in the primary slot also needs to be retained in flash so that it can be used
Francesco Servidio482921f2021-10-20 15:42:59 +0200881later. Furthermore, both images need to be recoverable if the bootloader
Christopher Collins92ea77f2016-12-12 15:59:26 -0800882resets in the middle of the swap operation. The two images are swapped
883according to the following procedure:
884
Fabio Utzig60319ac2019-09-06 08:29:50 -03008851. Determine if both slots are compatible enough to have their images swapped.
886 To be compatible, both have to have only sectors that can fit into the
887 scratch area and if one of them has larger sectors than the other, it must
888 be able to entirely fit some rounded number of sectors from the other slot.
Fabio Utzigc28005b2019-09-10 12:18:29 -0300889 In the next steps we'll use the terminology "region" for the total amount of
890 data copied/erased because this can be any amount of sectors depending on
891 how many the scratch is able to fit for some swap operation.
8922. Iterate the list of region indices in descending order (i.e., starting
893 with the greatest index); only regions that are predetermined to be part of
Fabio Utzig60319ac2019-09-06 08:29:50 -0300894 the image are copied; current element = "index".
895 + a. Erase scratch area.
896 + b. Copy secondary_slot[index] to scratch area.
Fabio Utzigc28005b2019-09-10 12:18:29 -0300897 - If this is the last region in the slot, scratch area has a temporary
Fabio Utzig60319ac2019-09-06 08:29:50 -0300898 status area initialized to store the initial state, because the
Fabio Utzigc28005b2019-09-10 12:18:29 -0300899 primary slot's last region will have to be erased. In this case,
Fabio Utzig60319ac2019-09-06 08:29:50 -0300900 only the data that was calculated to amount to the image is copied.
Fabio Utzigc28005b2019-09-10 12:18:29 -0300901 - Else if this is the first swapped region but not the last region in
Fabio Utzig60319ac2019-09-06 08:29:50 -0300902 the slot, initialize the status area in primary slot and copy the
Fabio Utzigc28005b2019-09-10 12:18:29 -0300903 full region contents.
904 - Else, copy entire region contents.
Fabio Utzig60319ac2019-09-06 08:29:50 -0300905 + c. Write updated swap status (i).
906 + d. Erase secondary_slot[index]
907 + e. Copy primary_slot[index] to secondary_slot[index] according to amount
908 previosly copied at step b.
Fabio Utzigc28005b2019-09-10 12:18:29 -0300909 - If this is not the last region in the slot, erase the trailer in the
Fabio Utzig60319ac2019-09-06 08:29:50 -0300910 secondary slot, to always use the one in the primary slot.
911 + f. Write updated swap status (ii).
912 + g. Erase primary_slot[index].
913 + h. Copy scratch area to primary_slot[index] according to amount
914 previously copied at step b.
Fabio Utzigc28005b2019-09-10 12:18:29 -0300915 - If this is the last region in the slot, the status is read from
Fabio Utzig60319ac2019-09-06 08:29:50 -0300916 scratch (where it was stored temporarily) and written anew in the
917 primary slot.
918 + i. Write updated swap status (iii).
9193. Persist completion of swap procedure to the primary slot image trailer.
Christopher Collins92ea77f2016-12-12 15:59:26 -0800920
David Vincze2d736ad2019-02-18 11:50:22 +0100921The additional caveats in step 2f are necessary so that the secondary slot image
Christopher Collinsfd7eb5c2016-12-21 13:46:08 -0800922trailer can be written by the user at a later time. With the image trailer
David Vincze2d736ad2019-02-18 11:50:22 +0100923unwritten, the user can test the image in the secondary slot
Håkon Øye Amundsen11d91c32020-03-04 08:49:47 +0000924(i.e., transition to state I).
Christopher Collins92ea77f2016-12-12 15:59:26 -0800925
Francesco Servidio2fe449d2021-10-21 12:38:36 +0200926---
927***Note***
Fabio Utzig5bd4e582017-07-20 08:55:38 -0300928
Francesco Servidio2fe449d2021-10-21 12:38:36 +0200929*If the region being copied contains the last sector, then swap status is*
930*temporarily maintained on scratch for the duration of this operation, always*
931*using the primary slot's area otherwise.*
932
933---
934***Note***
935
936*The bootloader tries to copy only used sectors (based on largest image*
937*installed on any of the slots), minimizing the amount of sectors copied and*
938*reducing the amount of time required for a swap operation.*
939
940---
Fabio Utzig5bd4e582017-07-20 08:55:38 -0300941
Christopher Collinsfd7eb5c2016-12-21 13:46:08 -0800942The particulars of step 3 vary depending on whether an image is being tested,
David Vincze2d736ad2019-02-18 11:50:22 +0100943permanently used, reverted or a validation failure of the secondary slot
944happened when a swap was requested:
Fabio Utzig86fe4b22017-07-28 18:56:29 -0300945
Christopher Collins92ea77f2016-12-12 15:59:26 -0800946 * test:
David Vincze2d736ad2019-02-18 11:50:22 +0100947 o Write primary_slot.copy_done = 1
Christopher Collinsfd7eb5c2016-12-21 13:46:08 -0800948 (swap caused the following values to be written:
David Vincze2d736ad2019-02-18 11:50:22 +0100949 primary_slot.magic = BOOT_MAGIC
Håkon Øye Amundsencdf94c22020-03-04 08:52:31 +0000950 secondary_slot.magic = UNSET
David Vincze2d736ad2019-02-18 11:50:22 +0100951 primary_slot.image_ok = Unset)
Christopher Collinsfd7eb5c2016-12-21 13:46:08 -0800952
953 * permanent:
David Vincze2d736ad2019-02-18 11:50:22 +0100954 o Write primary_slot.copy_done = 1
Christopher Collinsfd7eb5c2016-12-21 13:46:08 -0800955 (swap caused the following values to be written:
David Vincze2d736ad2019-02-18 11:50:22 +0100956 primary_slot.magic = BOOT_MAGIC
Håkon Øye Amundsencdf94c22020-03-04 08:52:31 +0000957 secondary_slot.magic = UNSET
David Vincze2d736ad2019-02-18 11:50:22 +0100958 primary_slot.image_ok = 0x01)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800959
960 * revert:
David Vincze2d736ad2019-02-18 11:50:22 +0100961 o Write primary_slot.copy_done = 1
962 o Write primary_slot.image_ok = 1
Fabio Utzig86fe4b22017-07-28 18:56:29 -0300963 (swap caused the following values to be written:
David Vincze2d736ad2019-02-18 11:50:22 +0100964 primary_slot.magic = BOOT_MAGIC)
Fabio Utzig86fe4b22017-07-28 18:56:29 -0300965
David Vincze2d736ad2019-02-18 11:50:22 +0100966 * failure to validate the secondary slot:
967 o Write primary_slot.image_ok = 1
Fabio Utzig86fe4b22017-07-28 18:56:29 -0300968
David Vincze2d736ad2019-02-18 11:50:22 +0100969After completing the operations as described above the image in the primary slot
970should be booted.
Christopher Collins92ea77f2016-12-12 15:59:26 -0800971
Francesco Servidio5bc98322021-11-03 13:19:22 +0100972## [Swap status](#swap-status)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800973
Francesco Servidio482921f2021-10-20 15:42:59 +0200974The swap status region allows the bootloader to recover in case it restarts in
Christopher Collins92ea77f2016-12-12 15:59:26 -0800975the middle of an image swap operation. The swap status region consists of a
976series of single-byte records. These records are written independently, and
977therefore must be padded according to the minimum write size imposed by the
978flash hardware. In the below figure, a min-write-size of 1 is assumed for
979simplicity. The structure of the swap status region is illustrated below. In
980this figure, a min-write-size of 1 is assumed for simplicity.
981
David Brown17e20d12017-09-12 11:53:20 -0600982```
Christopher Collins92ea77f2016-12-12 15:59:26 -0800983 0 1 2 3
984 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
985 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
986 |sec127,state 0 |sec127,state 1 |sec127,state 2 |sec126,state 0 |
987 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
988 |sec126,state 1 |sec126,state 2 |sec125,state 0 |sec125,state 1 |
989 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
990 |sec125,state 2 | |
991 +-+-+-+-+-+-+-+-+ +
992 ~ ~
993 ~ [Records for indices 124 through 1 ~
994 ~ ~
995 ~ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
996 ~ |sec000,state 0 |sec000,state 1 |sec000,state 2 |
997 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
David Brown17e20d12017-09-12 11:53:20 -0600998```
Christopher Collins92ea77f2016-12-12 15:59:26 -0800999
1000The above is probably not helpful at all; here is a description in English.
1001
1002Each image slot is partitioned into a sequence of flash sectors. If we were to
1003enumerate the sectors in a single slot, starting at 0, we would have a list of
1004sector indices. Since there are two image slots, each sector index would
1005correspond to a pair of sectors. For example, sector index 0 corresponds to
David Vincze2d736ad2019-02-18 11:50:22 +01001006the first sector in the primary slot and the first sector in the secondary slot.
1007Finally, reverse the list of indices such that the list starts with index
1008`BOOT_MAX_IMG_SECTORS - 1` and ends with 0. The swap status region is a
1009representation of this reversed list.
Christopher Collins92ea77f2016-12-12 15:59:26 -08001010
1011During a swap operation, each sector index transitions through four separate
1012states:
David Brown17e20d12017-09-12 11:53:20 -06001013```
David Vincze2d736ad2019-02-18 11:50:22 +010010140. primary slot: image 0, secondary slot: image 1, scratch: N/A
10151. primary slot: image 0, secondary slot: N/A, scratch: image 1 (1->s, erase 1)
10162. primary slot: N/A, secondary slot: image 0, scratch: image 1 (0->1, erase 0)
10173. primary slot: image 1, secondary slot: image 0, scratch: N/A (s->0)
David Brown17e20d12017-09-12 11:53:20 -06001018```
Christopher Collins92ea77f2016-12-12 15:59:26 -08001019
Francesco Servidio482921f2021-10-20 15:42:59 +02001020Each time a sector index transitions to a new state, the bootloader writes a
1021record to the swap status region. Logically, the bootloader only needs one
Christopher Collins92ea77f2016-12-12 15:59:26 -08001022record per sector index to keep track of the current swap state. However, due
1023to limitations imposed by flash hardware, a record cannot be overwritten when
Francesco Servidio482921f2021-10-20 15:42:59 +02001024an index's state changes. To solve this problem, the bootloader uses three
Christopher Collins92ea77f2016-12-12 15:59:26 -08001025records per sector index rather than just one.
1026
1027Each sector-state pair is represented as a set of three records. The record
1028values map to the above four states as follows
1029
David Brown17e20d12017-09-12 11:53:20 -06001030```
Christopher Collins92ea77f2016-12-12 15:59:26 -08001031 | rec0 | rec1 | rec2
1032 --------+------+------+------
1033 state 0 | 0xff | 0xff | 0xff
1034 state 1 | 0x01 | 0xff | 0xff
1035 state 2 | 0x01 | 0x02 | 0xff
1036 state 3 | 0x01 | 0x02 | 0x03
David Brown17e20d12017-09-12 11:53:20 -06001037```
Christopher Collins92ea77f2016-12-12 15:59:26 -08001038
Fabio Utzig2c05f1b2018-04-04 10:35:17 -03001039The swap status region can accommodate `BOOT_MAX_IMG_SECTORS` sector indices.
David Vincze2d736ad2019-02-18 11:50:22 +01001040Hence, the size of the region, in bytes, is
1041`BOOT_MAX_IMG_SECTORS * min-write-size * 3`. The only requirement for the index
1042count is that it is great enough to account for a maximum-sized image
1043(i.e., at least as great as the total sector count in an image slot). If a
1044device's image slots have been configured with `BOOT_MAX_IMG_SECTORS: 128` and
1045use less than 128 sectors, the first record that gets written will be somewhere
1046in the middle of the region. For example, if a slot uses 64 sectors, the first
1047sector index that gets swapped is 63, which corresponds to the exact halfway
1048point within the region.
Christopher Collins92ea77f2016-12-12 15:59:26 -08001049
Francesco Servidio2fe449d2021-10-21 12:38:36 +02001050---
1051***Note***
1052
1053*Since the scratch area only ever needs to record swapping of the last*
1054*sector, it uses at most min-write-size * 3 bytes for its own status area.*
1055
1056---
Fabio Utzig5bd4e582017-07-20 08:55:38 -03001057
Francesco Servidio5bc98322021-11-03 13:19:22 +01001058## [Reset recovery](#reset-recovery)
Christopher Collins92ea77f2016-12-12 15:59:26 -08001059
Francesco Servidio482921f2021-10-20 15:42:59 +02001060If the bootloader resets in the middle of a swap operation, the two images may
Christopher Collins92ea77f2016-12-12 15:59:26 -08001061be discontiguous in flash. Bootutil recovers from this condition by using the
Fabio Utzig86fe4b22017-07-28 18:56:29 -03001062image trailers to determine how the image parts are distributed in flash.
Christopher Collins92ea77f2016-12-12 15:59:26 -08001063
1064The first step is determine where the relevant swap status region is located.
1065Because this region is embedded within the image slots, its location in flash
Fabio Utzig86fe4b22017-07-28 18:56:29 -03001066changes during a swap operation. The below set of tables map image trailers
Christopher Collins92ea77f2016-12-12 15:59:26 -08001067contents to swap status location. In these tables, the "source" field
David Vinczeba3bd602019-06-17 16:01:43 +02001068indicates where the swap status region is located. In case of multi image boot
1069the images primary area and the single scratch area is always examined in pairs.
1070If swap status found on scratch area then it might not belong to the current
1071image. The swap_info field of swap status stores the corresponding image number.
1072If it does not match then "source: none" is returned.
Christopher Collins92ea77f2016-12-12 15:59:26 -08001073
David Brown17e20d12017-09-12 11:53:20 -06001074```
David Vincze2d736ad2019-02-18 11:50:22 +01001075 | primary slot | scratch |
1076 ----------+--------------+--------------|
1077 magic | Good | Any |
1078 copy-done | 0x01 | N/A |
1079 ----------+--------------+--------------'
1080 source: none |
1081 ----------------------------------------'
Marti Bolivar49b29172017-08-04 14:50:51 -04001082
David Vincze2d736ad2019-02-18 11:50:22 +01001083 | primary slot | scratch |
1084 ----------+--------------+--------------|
1085 magic | Good | Any |
1086 copy-done | 0xff | N/A |
1087 ----------+--------------+--------------'
1088 source: primary slot |
1089 ----------------------------------------'
Marti Bolivar49b29172017-08-04 14:50:51 -04001090
David Vincze2d736ad2019-02-18 11:50:22 +01001091 | primary slot | scratch |
1092 ----------+--------------+--------------|
1093 magic | Any | Good |
1094 copy-done | Any | N/A |
1095 ----------+--------------+--------------'
1096 source: scratch |
1097 ----------------------------------------'
Marti Bolivar49b29172017-08-04 14:50:51 -04001098
David Vincze2d736ad2019-02-18 11:50:22 +01001099 | primary slot | scratch |
1100 ----------+--------------+--------------|
1101 magic | Unset | Any |
1102 copy-done | 0xff | N/A |
1103 ----------+--------------+--------------|
1104 source: primary slot |
1105 ----------------------------------------+------------------------------+
1106 This represents one of two cases: |
1107 o No swaps ever (no status to read, so no harm in checking). |
1108 o Mid-revert; status in the primary slot. |
1109 For this reason we assume the primary slot as source, to trigger a |
1110 check of the status area and find out if there was swapping under way. |
1111 -----------------------------------------------------------------------'
David Brown17e20d12017-09-12 11:53:20 -06001112```
Christopher Collins92ea77f2016-12-12 15:59:26 -08001113
Francesco Servidio4ff0c182021-10-20 15:27:16 +02001114If the swap status region indicates that the images are not contiguous, MCUboot
Christopher Collinsa1c12042019-05-23 14:00:28 -07001115determines the type of swap operation that was interrupted by reading the `swap
Håkon Øye Amundsencbf30472019-07-24 08:34:03 +00001116info` field in the active image trailer and extracting the swap type from bits
David Vinczee2453472019-06-17 12:31:59 +020011170-3 then resumes the operation. In other words, it applies the procedure defined
1118in the previous section, moving image 1 into the primary slot and image 0 into
1119the secondary slot. If the boot status indicates that an image part is present
1120in the scratch area, this part is copied into the correct location by starting
1121at step e or step h in the area-swap procedure, depending on whether the part
1122belongs to image 0 or image 1.
Christopher Collins92ea77f2016-12-12 15:59:26 -08001123
Francesco Servidio482921f2021-10-20 15:42:59 +02001124After the swap operation has been completed, the bootloader proceeds as though
Christopher Collins92ea77f2016-12-12 15:59:26 -08001125it had just been started.
1126
Francesco Servidio5bc98322021-11-03 13:19:22 +01001127## [Integrity check](#integrity-check)
Christopher Collins92ea77f2016-12-12 15:59:26 -08001128
1129An image is checked for integrity immediately before it gets copied into the
Francesco Servidio482921f2021-10-20 15:42:59 +02001130primary slot. If the bootloader doesn't perform an image swap, then it can
David Vincze2d736ad2019-02-18 11:50:22 +01001131perform an optional integrity check of the image in the primary slot if
1132`MCUBOOT_VALIDATE_PRIMARY_SLOT` is set, otherwise it doesn't perform an
1133integrity check.
Christopher Collins92ea77f2016-12-12 15:59:26 -08001134
Francesco Servidio482921f2021-10-20 15:42:59 +02001135During the integrity check, the bootloader verifies the following aspects of
Christopher Collins92ea77f2016-12-12 15:59:26 -08001136an image:
Fabio Utzig75b34412019-09-06 08:30:43 -03001137
Fabio Utzigfd140ec2019-09-12 14:37:48 -03001138 * 32-bit magic number must be correct (`IMAGE_MAGIC`).
Fabio Utzig75b34412019-09-06 08:30:43 -03001139 * Image must contain an `image_tlv_info` struct, identified by its magic
Fabio Utzigfd140ec2019-09-12 14:37:48 -03001140 (`IMAGE_TLV_PROT_INFO_MAGIC` or `IMAGE_TLV_INFO_MAGIC`) exactly following
1141 the firmware (`hdr_size` + `img_size`). If `IMAGE_TLV_PROT_INFO_MAGIC` is
1142 found then after `ih_protect_tlv_size` bytes, another `image_tlv_info`
1143 with magic equal to `IMAGE_TLV_INFO_MAGIC` must be present.
Fabio Utzig75b34412019-09-06 08:30:43 -03001144 * Image must contain a SHA256 TLV.
1145 * Calculated SHA256 must match SHA256 TLV contents.
1146 * Image *may* contain a signature TLV. If it does, it must also have a
1147 KEYHASH TLV with the hash of the key that was used to sign. The list of
1148 keys will then be iterated over looking for the matching key, which then
1149 will then be used to verify the image contents.
Christopher Collins92ea77f2016-12-12 15:59:26 -08001150
Wouter Cappellebb7a39d2021-05-03 16:44:44 +02001151For low performance MCU's where the validation is a heavy process at boot
1152(~1-2 seconds on a arm-cortex-M0), the `MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE`
1153could be used. This option will cache the validation result as described above
1154into the magic area of the primary slot. The next boot, the validation will be
1155skipped if the previous validation was succesfull. This option is reducing the
1156security level since if an attacker could modify the contents of the flash after
1157a good image has been validated, the attacker could run his own image without
1158running validation again. Enabling this option should be done with care.
1159
Fabio Utzigd37d8772019-12-03 10:32:18 -03001160## [Security](#security)
Christopher Collins92ea77f2016-12-12 15:59:26 -08001161
1162As indicated above, the final step of the integrity check is signature
Francesco Servidio482921f2021-10-20 15:42:59 +02001163verification. The bootloader can have one or more public keys embedded in it
1164at build time. During signature verification, the bootloader verifies that an
Håkon Øye Amundsencbf30472019-07-24 08:34:03 +00001165image was signed with a private key that corresponds to the embedded KEYHASH
Fabio Utzigea422c22017-09-11 11:02:47 -03001166TLV.
Christopher Collins92ea77f2016-12-12 15:59:26 -08001167
Francesco Servidio482921f2021-10-20 15:42:59 +02001168For information on embedding public keys in the bootloader, as well as
Fabio Utzig4dce6aa2018-02-12 15:31:32 -02001169producing signed images, see: [signed_images](signed_images.md).
Fabio Utzigcdfa11a2018-10-01 09:45:54 -03001170
1171If you want to enable and use encrypted images, see:
1172[encrypted_images](encrypted_images.md).
David Vinczee32483f2019-06-13 10:46:24 +02001173
Francesco Servidio2fe449d2021-10-21 12:38:36 +02001174---
1175***Note***
1176
1177*Image encryption is not supported when the direct-xip upgrade strategy*
1178*is selected.*
1179
1180---
David Vinczee574f2d2020-07-10 11:42:03 +02001181
Francesco Servidio5bc98322021-11-03 13:19:22 +01001182### [Using hardware keys for verification](#hw-key-support)
David Vincze25459bf2020-04-21 17:11:20 +02001183
1184By default, the whole public key is embedded in the bootloader code and its
1185hash is added to the image manifest as a KEYHASH TLV entry. As an alternative
1186the bootloader can be made independent of the keys by setting the
1187`MCUBOOT_HW_KEY` option. In this case the hash of the public key must be
Francesco Servidio4ff0c182021-10-20 15:27:16 +02001188provisioned to the target device and MCUboot must be able to retrieve the
David Vincze25459bf2020-04-21 17:11:20 +02001189key-hash from there. For this reason the target must provide a definition
1190for the `boot_retrieve_public_key_hash()` function which is declared in
1191`boot/bootutil/include/bootutil/sign_key.h`. It is also required to use
1192the `full` option for the `--public-key-format` imgtool argument in order to
1193add the whole public key (PUBKEY TLV) to the image manifest instead of its
1194hash (KEYHASH TLV). During boot the public key is validated before using it for
Francesco Servidio4ff0c182021-10-20 15:27:16 +02001195signature verification, MCUboot calculates the hash of the public key from the
David Vincze25459bf2020-04-21 17:11:20 +02001196TLV area and compares it with the key-hash that was retrieved from the device.
Francesco Servidio4ff0c182021-10-20 15:27:16 +02001197This way MCUboot is independent from the public key(s). The key(s) can be
David Vincze25459bf2020-04-21 17:11:20 +02001198provisioned any time and by different parties.
1199
Fabio Utzigd37d8772019-12-03 10:32:18 -03001200## [Protected TLVs](#protected-tlvs)
Fabio Utzigfd140ec2019-09-12 14:37:48 -03001201
1202If the TLV area contains protected TLV entries, by beginning with a `struct
1203image_tlv_info` with a magic value of `IMAGE_TLV_PROT_INFO_MAGIC` then the
1204data of those TLVs must also be integrity and authenticity protected. Beyond
1205the full size of the protected TLVs being stored in the `image_tlv_info`,
1206the size of the protected TLVs together with the size of the `image_tlv_info`
1207struct itself are also saved in the `ih_protected_size` field inside the
1208header.
1209
1210Whenever an image has protected TLVs the SHA256 has to be calculated over
1211not just the image header and the image but also the TLV info header and the
1212protected TLVs.
1213
1214```
1215A +---------------------+
1216 | Header | <- struct image_header
1217 +---------------------+
1218 | Payload |
1219 +---------------------+
1220 | TLV area |
1221 | +-----------------+ | struct image_tlv_info with
1222 | | TLV area header | | <- IMAGE_TLV_PROT_INFO_MAGIC (optional)
1223 | +-----------------+ |
1224 | | Protected TLVs | | <- Protected TLVs (struct image_tlv)
1225B | +-----------------+ |
1226 | | TLV area header | | <- struct image_tlv_info with IMAGE_TLV_INFO_MAGIC
1227C | +-----------------+ |
1228 | | SHA256 hash | | <- hash from A - B (struct image_tlv)
1229D | +-----------------+ |
1230 | | Keyhash | | <- indicates which pub. key for sig (struct image_tlv)
1231 | +-----------------+ |
1232 | | Signature | | <- signature from C - D (struct image_tlv), only hash
1233 | +-----------------+ |
1234 +---------------------+
1235```
1236
Francesco Servidio5bc98322021-11-03 13:19:22 +01001237## [Dependency check](#dependency-check)
David Vinczee32483f2019-06-13 10:46:24 +02001238
Francesco Servidio4ff0c182021-10-20 15:27:16 +02001239MCUboot can handle multiple firmware images. It is possible to update them
David Vinczee32483f2019-06-13 10:46:24 +02001240independently but in many cases it can be desired to be able to describe
1241dependencies between the images (e.g. to ensure API compliance and avoid
1242interoperability issues).
1243
1244The dependencies between images can be described with additional TLV entries in
Fabio Utzigfd140ec2019-09-12 14:37:48 -03001245the protected TLV area after the end of an image. There can be more than one
1246dependency entry, but in practice if the platform only supports two individual
1247images then there can be maximum one entry which reflects to the other image.
David Vinczee32483f2019-06-13 10:46:24 +02001248
David Vinczee32483f2019-06-13 10:46:24 +02001249At the phase of dependency check all aborted swaps are finalized if there were
Francesco Servidio482921f2021-10-20 15:42:59 +02001250any. During the dependency check the bootloader verifies whether the image
David Vinczee32483f2019-06-13 10:46:24 +02001251dependencies are all satisfied. If at least one of the dependencies of an image
1252is not fulfilled then the swap type of that image has to be modified
1253accordingly and the dependency check needs to be restarted. This way the number
1254of unsatisfied dependencies will decrease or remain the same. There is always at
1255least 1 valid configuration. In worst case, the system returns to the initial
1256state after dependency check.
1257
1258For more information on adding dependency entries to an image,
1259see: [imgtool](imgtool.md).
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +00001260
Francesco Servidio5bc98322021-11-03 13:19:22 +01001261## [Downgrade prevention](#downgrade-prevention)
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +00001262
1263Downgrade prevention is a feature which enforces that the new image must have a
David Vinczec3084132020-02-18 14:50:47 +01001264higher version/security counter number than the image it is replacing, thus
1265preventing the malicious downgrading of the device to an older and possibly
1266vulnerable version of its firmware.
1267
Francesco Servidio5bc98322021-11-03 13:19:22 +01001268### [Software-based downgrade prevention](#sw-downgrade-prevention)
David Vinczec3084132020-02-18 14:50:47 +01001269
1270During the software based downgrade prevention the image version numbers are
1271compared. This feature is enabled with the `MCUBOOT_DOWNGRADE_PREVENTION`
1272option. In this case downgrade prevention is only available when the
1273overwrite-based image update strategy is used (i.e. `MCUBOOT_OVERWRITE_ONLY`
1274is set).
1275
Francesco Servidio5bc98322021-11-03 13:19:22 +01001276### [Hardware-based downgrade prevention](#hw-downgrade-prevention)
David Vinczec3084132020-02-18 14:50:47 +01001277
David Vincze25459bf2020-04-21 17:11:20 +02001278Each signed image can contain a security counter in its protected TLV area, which
1279can be added to the image using the `-s` option of the [imgtool](imgtool.md) script.
David Vinczec3084132020-02-18 14:50:47 +01001280During the hardware based downgrade prevention (alias rollback protection) the
1281new image's security counter will be compared with the currently active security
1282counter value which must be stored in a non-volatile and trusted component of
David Vincze25459bf2020-04-21 17:11:20 +02001283the device. It is beneficial to handle this counter independently from image
1284version number:
David Vinczec3084132020-02-18 14:50:47 +01001285
1286 * It does not need to increase with each software release,
1287 * It makes it possible to do software downgrade to some extent: if the
1288 security counter has the same value in the older image then it is accepted.
David Vincze25459bf2020-04-21 17:11:20 +02001289
1290It is an optional step of the image validation process and can be enabled with
1291the `MCUBOOT_HW_ROLLBACK_PROT` config option. When enabled, the target must
1292provide an implementation of the security counter interface defined in
1293`boot/bootutil/include/security_cnt.h`.
1294
1295## [Measured boot and data sharing](#boot-data-sharing)
1296
Francesco Servidio4ff0c182021-10-20 15:27:16 +02001297MCUboot defines a mechanism for sharing boot status information (also known as
David Vincze25459bf2020-04-21 17:11:20 +02001298measured boot) and an interface for sharing application specific information
1299with the runtime software. If any of these are enabled the target must provide
1300a shared data area between the bootloader and runtime firmware and define the
1301following parameters:
1302
1303```c
1304#define MCUBOOT_SHARED_DATA_BASE <area_base_addr>
1305#define MCUBOOT_SHARED_DATA_SIZE <area_size_in_bytes>
1306```
1307
1308In the shared memory area all data entries are stored in a type-length-value
1309(TLV) format. Before adding the first data entry, the whole area is overwritten
1310with zeros and a TLV header is added at the beginning of the area during an
1311initialization phase. This TLV header contains a `tlv_magic` field with a value
1312of `SHARED_DATA_TLV_INFO_MAGIC` and a `tlv_tot_len` field which is indicating
1313the total length of shared TLV area including this header. The header is
1314followed by the the data TLV entries which are composed from a
1315`shared_data_tlv_entry` header and the data itself. In the data header there is
1316a `tlv_type` field which identifies the consumer of the entry (in the runtime
1317software) and specifies the subtype of that data item. More information about
1318the `tlv_type` field and data types can be found in the
1319`boot/bootutil/include/bootutil/boot_status.h` file. The type is followed by a
1320`tlv_len` field which indicates the size of the data entry in bytes, not
1321including the entry header. After this header structure comes the actual data.
1322
1323```c
1324/** Shared data TLV header. All fields in little endian. */
1325struct shared_data_tlv_header {
1326 uint16_t tlv_magic;
1327 uint16_t tlv_tot_len; /* size of whole TLV area (including this header) */
1328};
1329
1330/** Shared data TLV entry header format. All fields in little endian. */
1331struct shared_data_tlv_entry {
1332 uint16_t tlv_type;
1333 uint16_t tlv_len; /* TLV data length (not including this header). */
1334};
1335```
1336
1337The measured boot can be enabled with the `MCUBOOT_MEASURED_BOOT` config option.
1338When enabled, the `--boot_record` argument of the imgtool script must also be
1339used during the image signing process to add a BOOT_RECORD TLV to the image
1340manifest. This TLV contains the following attributes/measurements of the
1341image in CBOR encoded format:
1342
1343 * Software type (role of the software component)
1344 * Software version
1345 * Signer ID (identifies the signing authority)
1346 * Measurement value (hash of the image)
1347 * Measurement type (algorithm used to calculate the measurement value)
1348
1349The `sw_type` string that is passed as the `--boot_record` option's parameter
1350will be the value of the "Software type" attribute in the generated BOOT_RECORD
1351TLV. The target must also define the `MAX_BOOT_RECORD_SZ` macro which indicates
1352the maximum size of the CBOR encoded boot record in bytes.
Francesco Servidio4ff0c182021-10-20 15:27:16 +02001353During boot, MCUboot will look for these TLVs (in case of multiple images) in
David Vincze25459bf2020-04-21 17:11:20 +02001354the manifests of the active images (the latest and validated) and copy the CBOR
1355encoded binary data to the shared data area. Preserving all these image
1356attributes from the boot stage for use by later runtime services (such as an
1357attestation service) is known as a measured boot.
1358
1359Setting the `MCUBOOT_DATA_SHARING` option enables the sharing of application
1360specific data using the same shared data area as for the measured boot. For
1361this, the target must provide a definition for the `boot_save_shared_data()`
1362function which is declared in `boot/bootutil/include/bootutil/boot_record.h`.
1363The `boot_add_data_to_shared_area()` function can be used for adding new TLV
1364entries to the shared data area.
Mate Toth-Palcbf9d392020-11-09 16:47:49 +01001365
1366## [Testing in CI](#testing-in-ci)
1367
1368### [Testing Fault Injection Hardening (FIH)](#testing-fih)
1369
1370The CI currently tests the Fault Injection Hardening feature of MCUboot by
1371executing instruction skip during execution, and looking at whether a corrupted
1372image was booted by the bootloader or not.
1373
1374The main idea is that instruction skipping can be automated by scripting a
1375debugger to automatically execute the following steps:
1376
1377- Set breakpoint at specified address.
1378- Continue execution.
1379- On breakpoint hit increase the Program Counter.
1380- Continue execution.
1381- Detach from target after a timeout reached.
1382
1383Whether or not the corrupted image was booted or not can be decided by looking
1384for certain entries in the log.
1385
1386As MCUboot is deployed on a microcontroller, testing FI would not make much
1387sense in the simulator environment running on a host machine with different
1388architecture than the MCU's, as the degree of hardening depends on compiler
1389behavior. For example, (a bit counterintuitively) the code produced by gcc
1390with `-O0` optimisation is more resilient against FI attacks than the code
1391generated with `-O3` or `-Os` optimizations.
1392
1393To run on a desired architecture in the CI, the tests need to be executed on an
1394emulator (as real devices are not available in the CI environment). For this
1395implementation QEMU is selected.
1396
1397For the tests MCUboot needs a set of drivers and an implementation of a main
1398function. For the purpose of this test Trusted-Firmware-M has been selected as
1399it supports Armv8-M platforms that are also emulated by QEMU.
1400
1401The tests run in a docker container inside the CI VMs, to make it more easy to
1402deploy build and test environment (QEMU, compilers, interpreters). The CI VMs
1403seems to be using quite old Ubuntu (16.04).
1404
1405The sequence of the testing is the following (pseudo code):
1406
1407```sh
1408fn main()
1409 # Implemented in ci/fih-tests_install.sh
1410 generate_docker_image(Dockerfile)
1411
1412 # See details below. Implemented in ci/fih-tests_run.sh.
1413 # Calling the function with different parameters is done by Travis CI based on
1414 # the values provided in the .travis.yaml
1415 start_docker_image(skip_sizes, build_type, damage_type, fih_level)
1416
1417fn start_docker_image(skip_sizes, build_type, damage_type, fih_level)
1418 # implemented in ci/fih_test_docker/execute_test.sh
1419 compile_mcuboot(build_type)
1420
1421 # implemented in ci/fih_test_docker/damage_image.py
1422 damage_image(damage_type)
1423
1424 # implemented in ci/fih_test_docker/run_fi_test.sh
1425 ranges = generate_address_ranges()
1426 for s in skip_sizes
1427 for r in ranges
1428 do_skip_in_qemu(s, r) # See details below
1429 evaluate_logs()
1430
1431fn do_skip_in_qemu(size, range)
1432 for a in r
1433 run_qemu(a, size) # See details below
1434
1435# this part is implemented in ci/fih_test_docker/fi_tester_gdb.sh
1436fn run_qemu(a, size)
1437 script = create_debugger_script(a, size)
1438 start_qemu_in_bacground() # logs serial out to a file
1439 gdb_attach_to_qemu(script)
1440 kill_qemu()
1441
1442 # This checks the debugger and the quemu logs, and decides whether the tets
1443 # was executed successfully, and whether the image is booted or not. Then
1444 # emits a yaml fragment on the standard out to be processed by the caller
1445 # script
1446 evaluate_run(qemu_log_file)
1447```
1448
1449Further notes:
1450
1451- The image is corrupted by changing its signature.
1452- MCUBOOT_FIH_PROFILE_MAX is not tested as it requires TRNG, and the AN521
1453platform has no support for it. However this profile adds the random
1454execution delay to the code, so should not affect the instruction skip results
1455too much, because break point is placed at exact address. But in practice this
1456makes harder the accurate timing of the attack.
1457- The test cases defined in .travis.yml always return `passed`, if they were
1458executed successfully. A yaml file is created during test execution with the
1459details of the test execution results. A summary of the collected results is
1460printed in the log at the end of the test.
1461
1462An advantage of having the tests running in a docker image is that it is
1463possible to run the tests on a local machine that has git and docker, without
1464installing any additional software.
1465
1466So, running the test on the host looks like the following (The commands below
1467are issued from the MCUboot source directory):
1468
1469```sh
Sherry Zhang3c4f69c2021-09-16 14:20:04 +08001470$ mkdir docker
Mate Toth-Palcbf9d392020-11-09 16:47:49 +01001471$ ./ci/fih-tests_install.sh
Tamas Ban04efc2e2022-12-08 17:46:26 +01001472$ FIH_LEVEL=MEDIUM BUILD_TYPE=RELEASE SKIP_SIZE=2 DAMAGE_TYPE=SIGNATURE \
1473 ./ci/fih-tests_run.sh
Mate Toth-Palcbf9d392020-11-09 16:47:49 +01001474```
1475On the travis CI the environment variables in the last command are set based on
1476the configs provided in the `.travis.yaml`
1477
1478This starts the tests, however the shell that it is running in is not
1479interactive, it is not possible to examine the results of the test run. To have
1480an interactive shell where the results can be examined, the following can be
1481done:
1482
1483- The docker image needs to be built with `ci/fih-tests_install.sh` as described
1484 above.
1485- Start the docker image with the following command:
1486 `docker run -i -t mcuboot/fih-test`.
1487- Execute the test with a command similar to the following:
1488 `/root/execute_test.sh 8 RELEASE SIGNATURE MEDIUM`. After the test finishes,
1489 the shell returns, and it is possible to investigate the results. It is also
1490 possible to stop the test with _Ctrl+c_. The parameters to the
1491 `execute_test.sh` are `SKIP_SIZE`, `BUILD_TYPE`, `DAMAGE_TYPE`, `FIH_LEVEL` in
Salome Thirot0f641972021-05-14 11:19:55 +01001492 order.