Carles Cufi | ecc34bb | 2018-01-22 18:02:46 +0100 | [diff] [blame] | 1 | # Building and using MCUboot with Zephyr |
| 2 | |
| 3 | MCUboot began its life as the bootloader for Mynewt. It has since |
| 4 | acquired the ability to be used as a bootloader for Zephyr as well. |
| 5 | There are some pretty significant differences in how apps are built |
| 6 | for Zephyr, and these are documented here. |
| 7 | |
Fabio Utzig | 4dce6aa | 2018-02-12 15:31:32 -0200 | [diff] [blame] | 8 | Please see the [design document](design.md) for documentation on the design |
| 9 | and operation of the bootloader itself. This functionality should be the same |
| 10 | on all supported RTOSs. |
Carles Cufi | ecc34bb | 2018-01-22 18:02:46 +0100 | [diff] [blame] | 11 | |
| 12 | The first step required for Zephyr is making sure your board has flash |
| 13 | partitions defined in its device tree. These partitions are: |
| 14 | |
| 15 | - `boot_partition`: for MCUboot itself |
| 16 | - `slot0_partition`: the primary image slot |
| 17 | - `slot1_partition`: the secondary image slot |
| 18 | - `scratch_partition`: the scratch slot |
| 19 | |
| 20 | Currently, the two image slots must be contiguous. If you are running |
| 21 | MCUboot as your stage 1 bootloader, `boot_partition` must be configured |
| 22 | so your SoC runs it out of reset. |
| 23 | |
| 24 | The flash partitions are typically defined in the Zephyr boards folder, in a |
| 25 | file named `boards/<arch>/<board>/<board>.dts`. An example `.dts` file with |
| 26 | flash partitions defined is the frdm_k64f's in |
| 27 | `boards/arm/frdm_k64f/frdm_k64f.dts`. Make sure the labels in your board's |
| 28 | `.dts` file match the ones used there. |
| 29 | |
| 30 | ## Building the bootloader itself |
| 31 | |
| 32 | The bootloader is an ordinary Zephyr application, at least from |
| 33 | Zephyr's point of view. There is a bit of configuration that needs to |
| 34 | be made before building it. Most of this can be done as documented in |
| 35 | the `CMakeLists.txt` file in boot/zephyr. There are comments there for |
| 36 | guidance. It is important to select a signature algorithm, and decide |
| 37 | if slot0 should be validated on every boot. |
| 38 | |
| 39 | To build MCUboot, create a build directory in boot/zephyr, and build |
| 40 | it as usual: |
| 41 | |
| 42 | ``` |
| 43 | cd boot/zephyr |
| 44 | mkdir build && cd build |
| 45 | cmake -GNinja -DBOARD=<board> .. |
| 46 | ninja |
| 47 | ``` |
| 48 | |
| 49 | In addition to the partitions defined in DTS, some additional |
| 50 | information about the flash layout is currently required to build |
| 51 | MCUboot itself. All the needed configuration is collected in |
| 52 | `boot/zephyr/include/target.h`. Depending on the board, this information |
| 53 | may come from board-specific headers, Device Tree, or be configured by |
| 54 | MCUboot on a per-SoC family basis. |
| 55 | |
| 56 | After building the bootloader, the binaries should reside in |
| 57 | `build/zephyr/zephyr.{bin,hex,elf}`, where `build` is the build |
| 58 | directory you chose when running `cmake`. Use the Zephyr build |
| 59 | system `flash` target to flash these binaries, usually by running |
Carles Cufi | 5a9688a | 2018-04-03 17:10:18 +0200 | [diff] [blame] | 60 | `make flash` (or `ninja flash`, etc.) from the build directory. Depending |
| 61 | on the target and flash tool used, this might erase the whole of the flash |
| 62 | memory (mass erase) or only the sectors where the boot loader resides prior to |
| 63 | programming the bootloader image itself. |
Carles Cufi | ecc34bb | 2018-01-22 18:02:46 +0100 | [diff] [blame] | 64 | |
| 65 | ## Building Applications for the bootloader |
| 66 | |
| 67 | In addition to flash partitions in DTS, some additional configuration |
| 68 | is required to build applications for MCUboot. |
| 69 | |
Carles Cufi | efd783c | 2018-03-26 17:55:40 +0200 | [diff] [blame] | 70 | This is handled internally by the Zephyr configuration system and is wrapped |
| 71 | in the `CONFIG_BOOTLOADER_MCUBOOT` Kconfig variable, which must be enabled in |
| 72 | the application's `prj.conf` file. |
| 73 | |
Carles Cufi | ecc34bb | 2018-01-22 18:02:46 +0100 | [diff] [blame] | 74 | The directory `samples/zephyr/hello-world` in the MCUboot tree contains |
| 75 | a simple application with everything you need. You can try it on your |
| 76 | board and then just make a copy of it to get started on your own |
| 77 | application; see samples/zephyr/README.md for a tutorial. |
| 78 | |
Carles Cufi | efd783c | 2018-03-26 17:55:40 +0200 | [diff] [blame] | 79 | The Zephyr `CONFIG_BOOTLOADER_MCUBOOT` configuration option |
| 80 | [documentation](http://docs.zephyrproject.org/reference/kconfig/CONFIG_BOOTLOADER_MCUBOOT.html) |
| 81 | provides additional details regarding the changes it makes to the image |
| 82 | placement and generation in order for an application to be bootable by |
| 83 | MCUboot. |
Carles Cufi | ecc34bb | 2018-01-22 18:02:46 +0100 | [diff] [blame] | 84 | |
| 85 | With this, build the application as your normally would. |
| 86 | |
| 87 | ### Signing the application |
| 88 | |
| 89 | In order to upgrade to an image (or even boot it, if |
| 90 | `MCUBOOT_VALIDATE_SLOT0` is enabled), the images must be signed. |
| 91 | To make development easier, MCUboot is distributed with some example |
| 92 | keys. It is important to stress that these should never be used for |
| 93 | production, since the private key is publicly available in this |
| 94 | repository. See below on how to make your own signatures. |
| 95 | |
David Brown | 520e31c | 2018-04-05 14:38:08 -0600 | [diff] [blame^] | 96 | Images can be signed with the `scripts/imgtool.py` script. It is best |
| 97 | to look at `samples/zephyr/Makefile` for examples on how to use this. |
Carles Cufi | ecc34bb | 2018-01-22 18:02:46 +0100 | [diff] [blame] | 98 | |
| 99 | ### Flashing the application |
| 100 | |
| 101 | The application itself can flashed with regular flash tools, but will |
Carles Cufi | 5a9688a | 2018-04-03 17:10:18 +0200 | [diff] [blame] | 102 | need to be programmed at the offset of slot-0 for this particular target. |
| 103 | Depending on the platform and flash tool you might need to manually specify a |
| 104 | flash offset corresponding to the slot-0 starting address. This is usually |
| 105 | not relevant for flash tools that use Intel Hex images (.hex) instead of raw |
| 106 | binary images (.bin) since the former include destination address information. |
| 107 | Additionally you will need to make sure that the flash tool does not perform |
| 108 | a mass erase (erasing the whole of the flash) or else you would be deleting |
| 109 | MCUboot. |
| 110 | These images can also be marked for upgrade, and loaded into slot-1, |
Carles Cufi | ecc34bb | 2018-01-22 18:02:46 +0100 | [diff] [blame] | 111 | at which point the bootloader should perform an upgrade. It is up to |
| 112 | the image to mark slot-0 as "image ok" before the next reboot, |
| 113 | otherwise the bootloader will revert the application. |
| 114 | |
| 115 | ## Managing signing keys |
| 116 | |
| 117 | The signing keys used by MCUboot are represented in standard formats, |
| 118 | and can be generated and processed using conventional tools. However, |
David Brown | 520e31c | 2018-04-05 14:38:08 -0600 | [diff] [blame^] | 119 | `scripts/imgtool.py` is able to generate key pairs in all of the |
| 120 | supported formats. See [the docs](imgtool.md) for more details on |
| 121 | this tool. |
Carles Cufi | ecc34bb | 2018-01-22 18:02:46 +0100 | [diff] [blame] | 122 | |
| 123 | ### Generating a new keypair |
| 124 | |
| 125 | Generating a keypair with imgtool is a matter of running the keygen |
| 126 | subcommand: |
| 127 | |
| 128 | ``` |
David Brown | 520e31c | 2018-04-05 14:38:08 -0600 | [diff] [blame^] | 129 | $ ./scripts/imgtool.py keygen -k mykey.pem -t rsa-2048 |
Carles Cufi | ecc34bb | 2018-01-22 18:02:46 +0100 | [diff] [blame] | 130 | ``` |
| 131 | |
| 132 | The argument to `-t` should be the desired key type. See the |
David Brown | 520e31c | 2018-04-05 14:38:08 -0600 | [diff] [blame^] | 133 | [the docs](imgtool.md) for more details on the possible key types. |
Carles Cufi | ecc34bb | 2018-01-22 18:02:46 +0100 | [diff] [blame] | 134 | |
| 135 | ### Extracting the public key |
| 136 | |
| 137 | The generated keypair above contains both the public and the private |
| 138 | key. It is necessary to extract the public key and insert it into the |
| 139 | bootloader. The keys live in `boot/zephyr/keys.c`, and can be |
| 140 | extracted using imgtool: |
| 141 | |
| 142 | ``` |
David Brown | 520e31c | 2018-04-05 14:38:08 -0600 | [diff] [blame^] | 143 | $ ./scripts/imgtool.py getpub -k mykey.pem |
Carles Cufi | ecc34bb | 2018-01-22 18:02:46 +0100 | [diff] [blame] | 144 | ``` |
| 145 | |
| 146 | This will output the public key as a C array that can be dropped |
| 147 | directly into the `keys.c` file. |
| 148 | |
| 149 | Once this is done, this new keypair file (`mykey.pem` in this |
| 150 | example) can be used to sign images. |