1# Building and using MCUboot with Zephyr 2 3MCUboot began its life as the bootloader for Mynewt. It has since 4acquired the ability to be used as a bootloader for Zephyr as well. 5There are some pretty significant differences in how apps are built 6for Zephyr, and these are documented here. 7 8Please see the [design document](design.md) for documentation on the design 9and operation of the bootloader itself. This functionality should be the same 10on all supported RTOSs. 11 12The first step required for Zephyr is making sure your board has flash 13partitions defined in its device tree. These partitions are: 14 15- `boot_partition`: for MCUboot itself 16- `slot0_partition`: the primary slot of Image 0 17- `slot1_partition`: the secondary slot of Image 0 18 19It is not recommended to use the swap-using-scratch algorithm of MCUboot, but 20if this operating mode is desired then the following flash partition is also 21needed (see end of this help file for details on creating a scratch partition 22and how to use the swap-using-scratch algorithm): 23 24- `scratch_partition`: the scratch slot 25 26Currently, the two image slots must be contiguous. If you are running 27MCUboot as your stage 1 bootloader, `boot_partition` must be configured 28so your SoC runs it out of reset. If there are multiple updateable images 29then the corresponding primary and secondary partitions must be defined for 30the rest of the images too (for example, `slot2_partition` and 31`slot3_partition` for Image 1). 32 33The flash partitions are typically defined in the Zephyr boards folder, in a 34file named `boards/<arch>/<board>/<board>.dts`. An example `.dts` file with 35flash partitions defined is the frdm_k64f's in 36`boards/arm/frdm_k64f/frdm_k64f.dts`. Make sure the DT node labels in your board's 37`.dts` file match the ones used there. 38 39## Installing requirements and dependencies 40 41Install additional packages required for development with MCUboot: 42 43``` 44 cd ~/mcuboot # or to your directory where MCUboot is cloned 45 pip3 install --user -r scripts/requirements.txt 46``` 47 48## Building the bootloader itself 49 50The bootloader is an ordinary Zephyr application, at least from 51Zephyr's point of view. There is a bit of configuration that needs to 52be made before building it. Most of this can be done as documented in 53the `CMakeLists.txt` file in boot/zephyr. There are comments there for 54guidance. It is important to select a signature algorithm, and decide 55if the primary slot should be validated on every boot. 56 57To build MCUboot, create a build directory in boot/zephyr, and build 58it as usual: 59 60``` 61 cd boot/zephyr 62 west build -b <board> 63``` 64 65In addition to the partitions defined in DTS, some additional 66information about the flash layout is currently required to build 67MCUboot itself. All the needed configuration is collected in 68`boot/zephyr/include/target.h`. Depending on the board, this information 69may come from board-specific headers, Device Tree, or be configured by 70MCUboot on a per-SoC family basis. 71 72After building the bootloader, the binaries should reside in 73`build/zephyr/zephyr.{bin,hex,elf}`, where `build` is the build 74directory you chose when running `west build`. Use `west flash` 75to flash these binaries from the build directory. Depending 76on the target and flash tool used, this might erase the whole of the flash 77memory (mass erase) or only the sectors where the bootloader resides prior to 78programming the bootloader image itself. 79 80## Building applications for the bootloader 81 82In addition to flash partitions in DTS, some additional configuration 83is required to build applications for MCUboot. 84 85This is handled internally by the Zephyr configuration system and is wrapped 86in the `CONFIG_BOOTLOADER_MCUBOOT` Kconfig variable, which must be enabled in 87the application's `prj.conf` file. 88 89The directory `samples/zephyr/hello-world` in the MCUboot tree contains 90a simple application with everything you need. You can try it on your 91board and then just make a copy of it to get started on your own 92application; see samples/zephyr/README.md for a tutorial. 93 94The Zephyr `CONFIG_BOOTLOADER_MCUBOOT` configuration option 95[documentation](http://docs.zephyrproject.org/reference/kconfig/CONFIG_BOOTLOADER_MCUBOOT.html) 96provides additional details regarding the changes it makes to the image 97placement and generation in order for an application to be bootable by 98MCUboot. 99 100With this, build the application as your normally would. 101 102### Signing the application 103 104In order to upgrade to an image (or even boot it, if 105`MCUBOOT_VALIDATE_PRIMARY_SLOT` is enabled), the images must be signed. 106To make development easier, MCUboot is distributed with some example 107keys. It is important to stress that these should never be used for 108production, since the private key is publicly available in this 109repository. See below on how to make your own signatures. 110 111Images can be signed with the `scripts/imgtool.py` script. It is best 112to look at `samples/zephyr/Makefile` for examples on how to use this. 113 114### Flashing the application 115 116The application itself can flashed with regular flash tools, but will 117need to be programmed at the offset of the primary slot for this particular 118target. Depending on the platform and flash tool you might need to manually 119specify a flash offset corresponding to the primary slot starting address. This 120is usually not relevant for flash tools that use Intel Hex images (.hex) instead 121of raw binary images (.bin) since the former include destination address 122information. Additionally you will need to make sure that the flash tool does 123not perform a mass erase (erasing the whole of the flash) or else you would be 124deleting MCUboot. 125These images can also be marked for upgrade, and loaded into the secondary slot, 126at which point the bootloader should perform an upgrade. It is up to 127the image to mark the primary slot as "image ok" before the next reboot, 128otherwise the bootloader will revert the application. 129 130## Managing signing keys 131 132The signing keys used by MCUboot are represented in standard formats, 133and can be generated and processed using conventional tools. However, 134`scripts/imgtool.py` is able to generate key pairs in all of the 135supported formats. See [the docs](imgtool.md) for more details on 136this tool. 137 138### Generating a new keypair 139 140Generating a keypair with imgtool is a matter of running the keygen 141subcommand: 142 143``` 144 $ ./scripts/imgtool.py keygen -k mykey.pem -t rsa-2048 145``` 146 147The argument to `-t` should be the desired key type. See the 148[the docs](imgtool.md) for more details on the possible key types. 149 150### Extracting the public key 151 152The generated keypair above contains both the public and the private 153key. It is necessary to extract the public key and insert it into the 154bootloader. Use the ``CONFIG_BOOT_SIGNATURE_KEY_FILE`` Kconfig option to 155provide the path to the key file so the build system can extract 156the public key in a format usable by the C compiler. 157The generated public key is saved in `build/zephyr/autogen-pubkey.h`, which is included 158by the `boot/zephyr/keys.c`. 159 160Currently, the Zephyr RTOS port limits its support to one keypair at the time, 161although MCUboot's key management infrastructure supports multiple keypairs. 162 163Once MCUboot is built, this new keypair file (`mykey.pem` in this 164example) can be used to sign images. 165 166## Using swap-using-scratch flash algorithm 167 168To use the swap-using-scratch flash algorithm, a scratch partition needs to be 169present for the target board which is used for holding the data being swapped 170from both slots, this section must be at least as big as the largest sector 171size of the 2 partitions (e.g. if a device has a primary slot in main flash 172with a sector size of 512 bytes and secondar slot in external off-chip flash 173with a sector size of 4KB then the scratch area must be at least 4KB in size). 174The number of sectors must also be evenly divisable by this sector size, e.g. 1754KB, 8KB, 12KB, 16KB are allowed, 7KB, 7.5KB are not. This scratch partition 176needs adding to the .dts file for the board, e.g. for the nrf52dk_nrf52832 177board thus would involve updating 178`<zephyr>/boards/arm/nrf52dk_nrf52832/nrf52dk_nrf52832.dts` with: 179 180``` 181 boot_partition: partition@0 { 182 label = "mcuboot"; 183 reg = <0x00000000 0xc000>; 184 }; 185 slot0_partition: partition@c000 { 186 label = "image-0"; 187 reg = <0x0000C000 0x37000>; 188 }; 189 slot1_partition: partition@43000 { 190 label = "image-1"; 191 reg = <0x00043000 0x37000>; 192 }; 193 storage_partition: partition@7a000 { 194 label = "storage"; 195 reg = <0x0007a000 0x00006000>; 196 }; 197``` 198 199Which would make the application size 220KB and scratch size 24KB (the nRF52832 200has a 4KB sector size so the size of the scratch partition can be reduced at 201the cost of vastly reducing flash lifespan, e.g. for a 32KB firmware update 202with an 8KB scratch area, the scratch area would be erased and programmed 8 203times per image upgrade/revert). To configure MCUboot to work in 204swap-using-scratch mode, the Kconfig value must be set when building it: 205`CONFIG_BOOT_SWAP_USING_SCRATCH=y`. 206 207Note that it is possible for an application to get into a stuck state when 208swap-using-scratch is used whereby an application has loaded a firmware update 209and marked it as test/confirmed but MCUboot will not swap the images and 210erasing the secondary slot from the zephyr application returns an error 211because the slot is marked for upgrade. 212 213## Serial recovery 214 215### Interface selection 216 217A serial recovery protocol is available over either a hardware serial port or a USB CDC ACM virtual serial port. 218The SMP server implementation can be enabled by the ``CONFIG_MCUBOOT_SERIAL=y`` Kconfig option. 219To set a type of an interface, use the ``BOOT_SERIAL_DEVICE`` Kconfig choice, and select either the ``CONFIG_BOOT_SERIAL_UART`` or the ``CONFIG_BOOT_SERIAL_CDC_ACM`` value. 220Which interface belongs to the protocol shall be set by the devicetree-chosen node: 221- `zephyr,console` - If a hardware serial port is used. 222- `zephyr,cdc-acm-uart` - If a virtual serial port is used. 223 224### Entering the serial recovery mode 225 226To enter the serial recovery mode, the device has to initiate rebooting, and a triggering event has to occur (for example, pressing a button). 227 228By default, the serial recovery GPIO pin active state enters the serial recovery mode. 229Use the ``mcuboot_button0`` devicetree button alias to assign the GPIO pin to the MCUboot. 230 231Alternatively, MCUboot can wait for a limited time to check if DFU is invoked by receiving an MCUmgr command. 232Select ``CONFIG_BOOT_SERIAL_WAIT_FOR_DFU=y`` to use this mode. ``CONFIG_BOOT_SERIAL_WAIT_FOR_DFU_TIMEOUT`` option defines 233the amount of time in milliseconds the device will wait for the trigger. 234 235### Direct image upload 236 237By default, the SMP server implementation will only use the first slot. 238To change it, invoke the `image upload` MCUmgr command with a selected image number, and make sure the ``CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y`` Kconfig option is enabled. 239Note that the ``CONFIG_UPDATEABLE_IMAGE_NUMBER`` Kconfig option adjusts the number of image-pairs supported by the MCUboot. 240 241The mapping of image number to partition is as follows: 242* 0 and 1 - image-0, the primary slot of the first image. 243* 2 - image-1, the secondary slot of the first image. 244* 3 - image-2. 245* 4 - image-3. 246 2470 is a default upload target when no explicit selection is done. 248 249### System-specific commands 250 251Use the ``CONFIG_ENABLE_MGMT_PERUSER=y`` Kconfig option to enable the following additional commands: 252* Storage erase - This command allows erasing the storage partition (enable with ``CONFIG_BOOT_MGMT_CUSTOM_STORAGE_ERASE=y``). 253* Custom image list - This command allows fetching version and installation status (custom properties) for all images (enable with ``CONFIG_BOOT_MGMT_CUSTOM_IMG_LIST=y``). 254 255### In-place image decryption 256 257Images uploaded by the serial recovery can be decrypted on the fly by using ECIES primitives described in the [ECIES encryption](encrypted_images.md#ecies-encryption) section. 258 259Enable support for this feature by using ``CONFIG_BOOT_SERIAL_ENCRYPT_EC256=y``. 260 261### More configuration 262 263For details on other available configuration options for the serial recovery protocol, check the Kconfig options (for example by using ``menuconfig``). 264