My main goal is to update the firmware over FOTA on a nRF5340, but with a signed firmware update file, and the bootloader verifies it. This is possible with mcuboot and works. But I also want to change the public key which mcuboot uses to verify the firmware updates, in case the private key got compromised, or is not available anymore. My idea for this is to use the dual stage bootloader setup, with b0 as the first bootloader, then mcuboot, and then the application. Since b0 can be configured with multiple keys, and the previous keys are not possible anymore when a new key is used, it would be possible to sign mcuboot with a new key for updating it in case it is needed.
I tried to set all config variables for it to my existing application, but got a few compiling problems. So for easier testing and getting help, I created a minimal application with the nRF5340-DK. It has a similar configuration, most important the external flash, which allows a bigger internal partition size for the internal application image.
It runs with the sdk-nrf 2.3.0. First checkout this version in a new directory:
west init -m github.com/.../sdk-nrf --mr v2.3.0
Then replace the "zephyr/samples/basic/blinky" project with this project: www.frank-buss.de/.../blinky.zip (a modified blinky app with the new settings and Bluetooth). It can then be compiled like this:
west build --board=nrf5340dk_nrf5340_cpuapp -p always
I can initially flash it with "west flash --recover". On ttyACM1 (in Linux) you can see this debug output, which shows first the b0 bootloader loading mcuboot, and then mcuboot loading the image:
*** Booting Zephyr OS build v3.2.99-ncs2 ***
Attempting to boot slot 0.
Attempting to boot from address 0x8200.
Verifying signature against key 0.
Hash: 0xa3...0d
Firmware signature verified.
Firmware version 1
I: Starting bootloader
I: Swap type: none
I: Swap type: none
I: Bootloader chainload address offset: 0x30000
�: Jumping to the first image slot
*** Booting Zephyr OS build v3.2.99-ncs2 ***
[00:00:00.002,288] <inf> main: Blinky application version 1 started
With "west build -t partition_manager_report" you can see the partition table, it should use the external flash for updating the app and network images:
external_flash (0x800000 - 8192kB):
+------------------------------------------------+
| 0x0: mcuboot_secondary (0xc0000 - 768kB) |
| 0xc0000: mcuboot_secondary_1 (0x40000 - 256kB) |
| 0x100000: external_flash (0x700000 - 7168kB) |
+------------------------------------------------+
flash_primary (0x100000 - 1024kB):
+--------------------------------------------------+
+---0x0: b0_container (0x8000 - 32kB)--------------+
| 0x0: b0 (0x8000 - 32kB) |
+---0x8000: s0 (0x10200 - 64kB)--------------------+
| 0x8000: s0_pad (0x200 - 512B) |
+---0x8200: s0_image (0x10000 - 64kB)--------------+
| 0x8200: mcuboot (0x10000 - 64kB) |
+--------------------------------------------------+
| 0x18200: EMPTY_0 (0x3e00 - 15kB) |
+---0x1c000: s1 (0x10200 - 64kB)-------------------+
| 0x1c000: s1_pad (0x200 - 512B) |
| 0x1c200: s1_image (0x10000 - 64kB) |
+--------------------------------------------------+
| 0x2c200: EMPTY_1 (0x3e00 - 15kB) |
+---0x30000: mcuboot_primary (0xc0000 - 768kB)-----+
| 0x30000: mcuboot_pad (0x200 - 512B) |
+---0x30200: app_image (0xbfe00 - 767kB)-----------+
+---0x30200: mcuboot_primary_app (0xbfe00 - 767kB)-+
| 0x30200: app (0xbfe00 - 767kB) |
+--------------------------------------------------+
| 0xf0000: nvs_storage (0x10000 - 64kB) |
+--------------------------------------------------+
otp (0x2fc - 764B):
+------------------------------------+
| 0xff8100: provision (0x280 - 640B) |
| 0xff8380: otp (0x7c - 124B) |
+------------------------------------+
ram_flash (0x40000 - 256kB):
+------------------------------------------+
| 0x0: mcuboot_primary_1 (0x40000 - 256kB) |
| 0x40000: ram_flash (0x0 - 0B) |
+------------------------------------------+
sram_primary (0x80000 - 512kB):
+-----------------------------------------------+
| 0x20000000: pcd_sram (0x2000 - 8kB) |
| 0x20002000: sram_primary (0x6e000 - 440kB) |
| 0x20070000: rpmsg_nrf53_sram (0x10000 - 64kB) |
+-----------------------------------------------+
CPUNET flash_primary (0x40000 - 256kB):
+--------------------------------------------+
+---0x1000000: b0n_container (0x8800 - 34kB)-+
| 0x1000000: b0n (0x8580 - 33kB) |
| 0x1008580: provision (0x280 - 640B) |
+---0x1008800: app (0x37800 - 222kB)---------+
| 0x1008800: hci_rpmsg (0x37800 - 222kB) |
+--------------------------------------------+
CPUNET sram_primary (0x10000 - 64kB):
+-------------------------------------------+
| 0x21000000: sram_primary (0x10000 - 64kB) |
+-------------------------------------------+
When I change the message in the app, and compile it again, and want to update it over FOTA with the file "build/zephyr/dfu_application.zip" and nRF Connect, then looks like the mobile app hangs, says just "Connecting", but it doesn't upload. This used to work without the extra settings for b0 etc. Is there some setting wrong or missing?
It also asked for pairing on the phone. It didn't do this before.
And it created the file "build/zephyr/dfu_mcuboot.zip". I guess this is for updating the mcuboot, but same problem hanging in nRF Connect. The LED still blinks, so the application still runs, and I can't see any error message on the console.
Another possible problem later will be the size of mcuboot. Looks like mcuboot is stored twice for the update process, instead also with the same concept as the app and network core in the external flash. This reduces the available flash for the app core a lot (I guess in parts because of the very big fash sector size of the internal flash as well). Is there any setting to reduce the mcuboot size, or even better, to store the update image in the external flash as well?
And can I combine the mcuboot update zip file with the application and network update zip file?