|
1 | 1 | # mbed-mcuboot-demo
|
2 |
| -Demo of mcuboot with Mbed |
| 2 | +Demo of mcuboot with Mbed-OS |
3 | 3 |
|
4 |
| -Initialize the mcuboot submodule: |
5 |
| -`git submodule init && git submodule update` |
| 4 | +This application builds as a bootloader and should be built with the [corresponding bootable blinky demo application](https://github.com/AGlass0fMilk/mbed-mcuboot-blinky). |
6 | 5 |
|
7 |
| -Pull the most recent mcuboot mbed port: |
8 |
| -`cd mcuboot && git checkout mbed-port && git pull` |
| 6 | +## Overview |
| 7 | + |
| 8 | +Go to the mcuboot repository for more information on mcuboot and how to configure it. This section will only cover topics specific to the mbed-os implementation. |
| 9 | + |
| 10 | +There is additonal information, such as an overview of memory regions and basic bootloader operation, in the mbed-mcuboot-blink repository linked to above. |
| 11 | + |
| 12 | +## Configuration |
| 13 | + |
| 14 | +Upon bootup, mcuboot looks at two memory regions, called "primary" and "secondary", to determine if a firmware update is available and should be installed. |
| 15 | + |
| 16 | +### Primary Memory Region |
| 17 | + |
| 18 | +The **"primary"** memory region is always the region of flash beginning where the bootable main application starts (the "application start address") and ending at the end of the physical flash address space **minus the mcuboot scratch memory area size**. |
| 19 | + |
| 20 | +### Scratch Region |
| 21 | + |
| 22 | +If configured as such, mcuboot can perform a "swap" update where it will copy the existing main application into the secondary memory region and the update candidate into the main application region. This allows mcuboot to revert the update in case of a serious firmware bug (ie: brick-proofs the update process). If the updated application fails to mark itself as "okay", mcuboot will revert the update upon the next boot cycle. |
| 23 | + |
| 24 | +To perform this kind of swap update, mcuboot requires a non-volatile "scratch" space in memory to store pieces of application code and update status information. This enables mcuboot to safely continue an update/revert procedure in the event of a power loss. |
| 25 | + |
| 26 | +The scratch region exists **at the end of the physical flash address space, just after the main application/primary memory region.** The size of the scratch space can be configured using `mcuboot.scratch-size` -- this value **must** be erase-sector aligned (ie: a multiple of the flash's eraseable size). |
| 27 | + |
| 28 | +Care should be exercised when configuring the bootable application to ensure the scratch space and application regions do not overlap. See the bootable blinky demo application readme for more information. |
| 29 | + |
| 30 | +### Secondary Memory Region |
| 31 | + |
| 32 | +The **"secondary"** memory region is provided by you. Typically this is an external flash chip used for bulk data and firmware update storage. |
| 33 | + |
| 34 | +In this example, the secondary memory region is initialized to the target's default block device instance in the following line of `flash_map.cpp` below: |
| 35 | + |
| 36 | +``` |
| 37 | +mbed::BlockDevice* mcuboot_secondary_bd = mbed::BlockDevice |
| 38 | +``` |
| 39 | + |
| 40 | +The symbol, `mcuboot_secondary_bd`, is an `extern` expected to be defined when `mcuboot.bootloader-build` is 1 (ie: you are building mcuboot as a bootloader and not an application library). |
| 41 | + |
| 42 | +Since the Mbed-OS mcuboot port uses Mbed's `BlockDevice` API, there is a lot of flexibility when providing the secondary memory region. For example, you can use a `FlashIAPBlockDevice` if your application is small enough to fit two copies in the internal flash. If you also use your external flash chip for data storage you can simply wrap the whole `BlockDevice` object in a `SlicingBlockDevice` to give mcuboot access to a certain region of your external flash. |
| 43 | + |
| 44 | +The Mbed-OS mcuboot port also has an additional function that the application can define if needed: `void mbed_mcuboot_user_init(void)`. This is provided as a `weak` symbol so the application can perform any necessary initialization before the rest of the boot process begins. |
| 45 | + |
| 46 | +## Binary Signing |
| 47 | + |
| 48 | +It is beneficial to first install mcuboot's imgtool python command line tool: |
| 49 | + |
| 50 | +`pip3 install --user -r mcuboot/scripts/requirements.txt && python3 mcuboot/scripts/setup.py install` |
| 51 | + |
| 52 | +This section will only cover steps specific to setting up this project with a signing key pair and signing a main application binary. For more advanced use cases and information, see the [mcuboot documentation](https://github.com/AGlass0fMilk/mcuboot/blob/mbed-port/docs/imgtool.md). |
| 53 | + |
| 54 | +For this project the required steps to sign an application are: |
| 55 | + |
| 56 | +1.) Generate an rsa2048 key pair: `imgtool keygen -k signing-keys.pem -t rsa-2048` |
| 57 | + |
| 58 | +2.) Extract the public key into a C data structure so it can be built into the bootloader: |
| 59 | + |
| 60 | +`imgtool getpub -k signing-keys.pem >> signing_keys.c` |
| 61 | + |
| 62 | +**Note:** The output of this command formats the variables to a specific name that is declared as an extern in mcuboot's sources. It must **not** be modified manually. |
| 63 | + |
| 64 | +3.) Once all other configuration has occured and the secondary flash BlockDevice has been declared, you may build the bootloader: `mbed compile` |
| 65 | + |
| 66 | +4.) Build the main application. The corresponding main application example can be cloned from this repository: [mbed-mcuboot-blinky](https://github.com/AGlass0fMilk/mbed-mcuboot-blinky). Follow the instructions in the README there and continue to the next step when the application hex/binary has been built. |
| 67 | + |
| 68 | +Briefly, the commands are (from the root directory of this repository): |
9 | 69 |
|
10 |
| -Build the mbed program: |
11 | 70 | ```
|
12 |
| -mbed target NRF52840_DK |
13 |
| -mbed toolchain GCC_ARM |
14 |
| -mbed compile |
| 71 | +git clone https://github.com/AGlass0fMilk/mbed-mcuboot-blinky.git ../mbed-mcuboot-blinky |
| 72 | +cd ../mbed-mcuboot-blinky |
| 73 | +mbed new . && mbed deploy |
| 74 | +mbed compile -t GCC_ARM -m NRF52840_DK |
| 75 | +cp BUILD/NRF52840_DK/GCC_ARM/mbed-mcuboot-blinky.hex ../mbed-mcuboot-demo |
| 76 | +cd &_ |
15 | 77 | ```
|
16 | 78 |
|
17 |
| -Flash bootloader application to the NRF52840_DK. |
| 79 | +5.) The next step is to sign the main application binary. |
18 | 80 |
|
19 |
| -Then flash the included `signed-usb.hex` to the NRF52840_DK. |
| 81 | +**Note:** even if the internal main application is not verified (ie: the digital signature is not checked) this step **must** be performed so the appropriate application header info is prepended to the binary. mcuboot will not execute the internal main application if this header info is missing or corrupt. |
20 | 82 |
|
21 |
| -This enables drag-and-drop programming of the target over USB MSD. |
| 83 | +``` |
| 84 | +imgtool sign -k signing-keys.pem --align 4 -v 1.2.3 --header-size 1024 --pad-header -S 901120 mbed-mcuboot-blinky.hex signed.hex |
| 85 | +``` |
22 | 86 |
|
23 |
| -Plug the NRF52840_DK's target USB connector into your laptop. It should show up as a 2MB flash drive. |
| 87 | +Explanation of each option: |
24 | 88 |
|
25 |
| -Copy the `signed.bin` binary over to the flash drive. You can watch serial output for progress of flashing. |
| 89 | +- `-k signing-keys.pem`: this specifies the file containing the keys used to sign/verify the application |
| 90 | +- `--align 4`: this lets mcuboot know the intrinsic alignment of the flash (32-bits = 4 byte alignemtn) |
| 91 | +- `-v 1.2.3`: this sets the version number of the application to 1.2.3 |
| 92 | +- `--header-size 1024`: this must be the same as the value specified in `mcuboot.header-size` configuration (1024 bytes by default) |
| 93 | +- `--pad-header`: this tells imgtool to insert the entire header, including any necessary padding bytes. |
| 94 | +- `-S 901120`: this specifies the maximum size of the application ("slot size"). It **must** be the same as the value specified in the **main application's** `target.mbed_app_size` configuration (0xDC000 = 901120) |
26 | 95 |
|
27 |
| -After a while the target should disconnect and start flashing itself... the on-board LED3 should start to blink when done. |
| 96 | +6.) Flash your target with both the mcuboot bootloader application and the signed main application |
0 commit comments