Using MCUBoot with nRF5340

Hello,

I try to figure out, how to correctly setup MCUboot for an nrf5340, so that:

  • Application is updatable
  • BT Stack is updatable
  • Firmware Updates are encrypted and signed
  • Updates are stored in external flash memory
  • No need to update the bootloader itself
  • Updates are stored on the external flash by some application specific protocol.

For that task, I upgraded our project to nrfconnect/sdk-nrf version v2.7.99-cs2. My current understanding is, that I want to use Sysbuild and have to define a static partition. I haven't found any comprehensive documentation, that defines exactly, which partitions are required for the given setup. So, I search for something in the examples, that could come close to my setup. The result of this example `pm_static.yml` looks like this:

app:
  address: 0x10200
  region: flash_primary
  size: 0xdfe00
mcuboot:
  address: 0x0
  region: flash_primary
  size: 0x10000
mcuboot_pad:
  address: 0x10000
  region: flash_primary
  size: 0x200
mcuboot_primary:
  address: 0x10000
  region: flash_primary
  size: 0xe0000
  span: [mcuboot_pad, app]
mcuboot_primary_app:
  address: 0x10200
  region: flash_primary
  size: 0xdfe00
  span: [app]
settings_storage:
  address: 0xf0000
  region: flash_primary
  size: 0x10000
mcuboot_primary_1:
  address: 0x0
  size: 0x40000
  device: nordic_ram_flash_controller
  region: ram_flash
mcuboot_secondary:
  address: 0x00000
  size: 0xe0000
  device: DT_CHOSEN(nordic_pm_ext_flash)
  region: external_flash
mcuboot_secondary_1:
  address: 0xe0000
  size: 0x40000
  device: DT_CHOSEN(nordic_pm_ext_flash)
  region: external_flash
external_flash:
  address: 0x120000
  size: 0x6e0000
  device: DT_CHOSEN(nordic_pm_ext_flash)
  region: external_flash
pcd_sram:
  address: 0x20000000
  size: 0x2000
  region: sram_primary

However, in the resulting `partition_manager_report`:

  external_flash (0x800000 - 8192kB): 
+------------------------------------------------+
| 0x0: mcuboot_secondary (0xe0000 - 896kB)       |
| 0xe0000: mcuboot_secondary_1 (0x40000 - 256kB) |
| 0x120000: external_flash (0x6e0000 - 7040kB)   |
+------------------------------------------------+

  flash_primary (0x100000 - 1024kB): 
+--------------------------------------------------+
| 0x0: mcuboot (0x10000 - 64kB)                    |
+---0x10000: mcuboot_primary (0xe0000 - 896kB)-----+
| 0x10000: mcuboot_pad (0x200 - 512B)              |
+---0x10200: mcuboot_primary_app (0xdfe00 - 895kB)-+
| 0x10200: app (0xdfe00 - 895kB)                   |
+--------------------------------------------------+
| 0xf0000: settings_storage (0x10000 - 64kB)       |
+--------------------------------------------------+

  otp (0x2fc - 764B): 
+------------------------------+
| 0xff8100: otp (0x2fc - 764B) |
+------------------------------+

  sram_primary (0x80000 - 512kB): 
+-----------------------------------------------+
| 0x20000000: pcd_sram (0x2000 - 8kB)           |
| 0x20002000: sram_primary (0x6e000 - 440kB)    |
| 0x20070000: rpmsg_nrf53_sram (0x10000 - 64kB) |
+-----------------------------------------------+

the partition `mcuboot_primary_1` is simply missing (and later the compilation of `nrf/modules/mcuboot/hooks/nrf53_hooks.c` fails with an undeclared symbol `PM_MCUBOOT_PRIMARY_1_ADDRESS`. 

I found this warning in the DTS parsing:

warning: FLASH_SIMULATOR (defined at drivers/flash/Kconfig.simulator:6) was assigned the value 'y'
but got the value 'n'. Check these unsatisfied dependencies: DT_HAS_ZEPHYR_SIM_FLASH_ENABLED (=n).
See http://docs.zephyrproject.org/latest/kconfig.html#CONFIG_FLASH_SIMULATOR and/or look up
FLASH_SIMULATOR in the menuconfig/guiconfig interface.

The referenced documentation just contains the sentence: "Enable the flash simulator."

What do I have to do, to use MCUBoot? 

Is there any comprehensive documentation, that clearly states, what is required to completely configure the bootloader?

Parents
  • Hello,

    I've created a demo based on the peripheral_lbs sample, please see attached below.

    Demo sample

    peripheral_lbs_enc_fota.zip

    Disclaimers

    - DFU with encrypted images is not a feature that has been tested or validated by Nordic ( nRF52840 + NCS + MCUBoot, CC310-enabled image encryption? ) .

    - The cmake signing script does not sign encrypt the netcore image. This can be fixed by patching relevant cmake script.

    - The application_dfu.zip generated by the build contains signed but not encrypted images. Use the /build/peripheral_lbs_fota_enc/zephyr/zephyr.signed.encrypted.bin binary instead (application image). The netcore image which is signed but not encrypted is called signed_by_mcuboot_and_b0_ipc_radio.bin and is located in build/.

    - I have not done any extensive testing of this demo, just verified that I was able to update the appcore FW.

    Best regards,

    Vidar

  • Thank you! I will go through that example.

    An other, very annoying observation I made: In the corse to, basically "try and error", figuring out some settings that fixes build errors, I found, that the build is not reproducible!

    Currently, I have a state, where I completely delete the build folder, start the build with `--pristine` added to the `west build` command and get alternating, two different errors. The one error, is the error above, while building the application.After I received that error, I delete the build folder again and rerun the build command. Every second time, I receive a linker error, while linking the application (a missing symbol, probably not defined due to the first issue).

    As the second error is a linker error, this can not be any effect from parallel build, where the order of build steps could change. I disable the usage of `ccache`, but the behavior does not change. :-/

  • Hi Vidar,

    I managed to add the used external NOR flash chip to the configuration (I had to name it mx25r64, even thought, it is a totally different chip. Otherwise, I got linker errors: `undefined reference to `__device_dts_ord_142'`).

    Now, all binaries (Application, Network, MCUBoot and b0n) are building. The bootloader starts, but refuses to start the binary in the primary slot:

    00> *** Booting MCUboot v2.1.0-dev-f30dce197f34 ***
    00> *** Using nRF Connect SDK v2.7.99-cs2-d73b286ff6d9 ***
    00> *** Using Zephyr OS v3.6.99-1b696c108812 ***
    00> [00:00:00.324,035] <inf> mcuboot: Starting bootloader
    00> [00:00:00.324,432] <wrn> mcuboot: Failed reading sectors; BOOT_MAX_IMG_SECTORS=128 - too small?
    00> [00:00:00.325,195] <inf> mcuboot: Image index: 1, Swap type: none
    00> [00:00:00.325,500] <err> mcuboot: Image in the primary slot is not valid!
    00> [00:00:00.325,531] <err> mcuboot: Unable to find bootable image

    At the primaries start address, there is an application (at least it looks like a vector table). So I guess, that MCUBoot is not able to correctly verify the image.

    During the build of MCUboot, there are log messages, that indicate, that the bootloader is build with the correct keys embedded:

    MCUBoot bootloader key file: <absoulte path to pem file>
    MCUBoot bootloader encryption key file: <absoulte path to pem file>

    While during the build of the application, I see this warning, that let me suspect, that maybe for the build of the application an other key is used.

          --------------------------------------------------------------
          --- WARNING: Using generated NSIB public/private key-pair. ---
          --- It should not be used for production.                  ---
          --- See SB_CONFIG_SECURE_BOOT_SIGNING_KEY_FILE             ---
          --------------------------------------------------------------

    Interesting enough, I saw the same discrepancy with your example. So, I toke an nRF5340 eval board and installed your example. But in that case, the application is running (I see a blinking LED and a connectable BLE service).

    As the primary is stored in internal flash memory, I suspect, that it could not be a problem of the configuration of the external flash memory.

    Any idea, as to what could be the problem here?

    best regards

    Torsten

  • Hi Torsten,

    Torsten Robitzki said:
    I managed to add the used external NOR flash chip to the configuration (I had to name it mx25r64, even thought, it is a totally different chip.

    The chosen must point to the flash device you have in your QSPI devictree node if it is not the same as the one on the DK.

    Torsten Robitzki said:
    Now, all binaries (Application, Network, MCUBoot and b0n) are building. The bootloader starts, but refuses to start the binary in the primary slot:

    Please create a new file named mcuboot.conf in your sysbuild folder that contain the following lines:

    # Configure MCUboot features
    CONFIG_BOOT_MAX_IMG_SECTORS=256
    CONFIG_MCUBOOT_DOWNGRADE_PREVENTION=y
    CONFIG_BOOT_ECDSA_TINYCRYPT=y
    
    # Enable flash simulator
    CONFIG_PCD_APP=y
    CONFIG_FLASH_SIMULATOR=y
    CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y
    CONFIG_FLASH_SIMULATOR_STATS=n
    
    CONFIG_NORDIC_QSPI_NOR=y
    CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096
    
    CONFIG_BOOT_IMAGE_ACCESS_HOOKS=y
    CONFIG_BOOT_IMAGE_ACCESS_HOOK_NRF5340=y
    
    CONFIG_MULTITHREADING=y

    The do a pristine build.

    Best regards,

    Vidar

  • Hi Vidar,

    my idea, was to define some device, similar to the mx25r64 (with a changed jedec-id, frequency, etc.) and then to pick that device with the `nordic,pm-ext-flash` in the chosen section:

    &qspi {
        flash_ext: MT25QU01GBBB@0 {
            compatible = "nordic,qspi-nor";
            reg = < 0x0 >;
            writeoc = "pp4io";
            readoc = "read4io";
            sck-frequency = < 90000000 >;
            jedec-id = [ 20 BB 21 ];
            sfdp-bfp = [ E5 20 F1 FF FF FF FF 03 44 EB 08 6B 08 3B 04 BB EE FF FF FF FF FF 00 FF FF FF 00 FF 0C 20 0F 52 10 D8 00 FF 23 72 F5 00 82 ED 04 CC 44 83 68 44 30 B0 30 B0 F7 C4 D5 5C 00 BE 29 FF F0 D0 FF FF ];
            size = < 0x4000000 >;
            has-dpd;
            t-enter-dpd = < 0x2710 >;
            t-exit-dpd = < 0x88b8 >;
        };
    };
    
    / {
        chosen {
            nordic,pm-ext-flash = &flash_ext;
        };
    };
    

    but this results in a linker error: "undefined reference to `__device_dts_ord_142`"

    When I rename the device above to `mx25r64: mx25r6435f@0`, everything works fine (including the jedec test in the driver). So anyway, I have a solution. I will add some comment to the configuration.

    For the bootloader itself: I found out, after some lengthy debugging, that the primary image was flashed with a RSA3072 hash, while MCUBoot was looking for a RSA2048 hash. The MCUBoot error message was: "Image in the primary slot is not valid!".

    After changing algorithm and key to ECDSA_P256, the bootloader is starting the application.

    Thanks a lot for your help,

    Torsten

  • Hi Torsten,

    Torsten Robitzki said:
    my idea, was to define some device, similar to the mx25r64 (with a changed jedec-id, frequency, etc.) and then to pick that device with the `nordic,pm-ext-flash` in the chosen section:

    Thanks for the clarification. The name should not matter as long as the actual configuration parameters match your flash ic. The JESD216 flash sample can be used to verify the configuration.

    Torsten Robitzki said:

    but this results in a linker error: "undefined reference to `__device_dts_ord_142`"

    When I rename the device above to `mx25r64: mx25r6435f@0`, everything works fine (including the jedec test in the driver). So anyway, I have a solution. I will add some comment to the configuration.

    The error suggests that the Kconfig symbol for this driver is not enabled (https://docs.zephyrproject.org/latest/build/dts/troubleshooting.html#undefined-reference-to-device-dts-ord-n). I assume '142' is referring to the flash_ext node in your build. So maybe CONFIG_NORDIC_QSPI_NOR did not get selected?

    Torsten Robitzki said:

    For the bootloader itself: I found out, after some lengthy debugging, that the primary image was flashed with a RSA3072 hash, while MCUBoot was looking for a RSA2048 hash. The MCUBoot error message was: "Image in the primary slot is not valid!".

    After changing algorithm and key to ECDSA_P256, the bootloader is starting the application.

    I would have assumed that this would lead to a build error, but it seems like that is not the case. I had SB_CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y in my sample.

    Best regards,

    Vidar

  • Hi Vidar,

    the linker error above happens, when I use a different name for the external flash memory. Only, when I name that chip mx25r64, I do not get that linker error.

    Thanks for the example, but it doesn't build correctly (board is unknown). When I change the board to  `nrf5340dk/nrf5340/cpuapp` I get some configuration warnings:

    warning: SPI_NOR (defined at soc/gaisler/gr716a/Kconfig.defconfig:18, drivers/flash/Kconfig.nor:4)
    was assigned the value 'y' but got the value 'n'. Check these unsatisfied dependencies: ((FLASH &&
    SOC_GR716A) || (DT_HAS_JEDEC_SPI_NOR_ENABLED && FLASH))

    The `CONFIG_NORDIC_QSPI_NOR` configuration was explicitly set to `y`. Then I change the device name to `flash_ext: MT25QU01GBBB@0 `:

    &qspi {
        /*
         * Name of the device has to be mx25r64; Otherwise,
         * the driver is not found during linking
         */
    /*    mx25r64: mx25r6435f@0 {*/
        flash_ext: MT25QU01GBBB@0 {
            compatible = "nordic,qspi-nor";
            reg = < 0x0 >;
            writeoc = "pp4io";
            readoc = "read4io";
            sck-frequency = < 90000000 >;
            jedec-id = [ 20 BB 21 ];
            sfdp-bfp = [ E5 20 F1 FF FF FF FF 03 44 EB 08 6B 08 3B 04 BB EE FF FF FF FF FF 00 FF FF FF 00 FF 0C 20 0F 52 10 D8 00 FF 23 72 F5 00 82 ED 04 CC 44 83 68 44 30 B0 30 B0 F7 C4 D5 5C 00 BE 29 FF F0 D0 FF FF ];
            size = < 0x8000000 >;
            has-dpd;
            t-enter-dpd = < 0x2710 >;
            t-exit-dpd = < 0x88b8 >;
        };
    };
    
    / {
        chosen {
    /*        nordic,pm-ext-flash = &mx25r64;*/
            nordic,pm-ext-flash = &flash_ext;
        };
    };
    

    I get an undefined symbol to `__device_dts_ord_142`.

    Yes, your example used `SB_CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y` and I even tried that setting and your keys on my course to find some configuration that builds. And as soon as it build, I changed it back to my keys and thus to the algorithm, I've picked.

    That's the major problem with examples. You never know, which bit is really important. Is the name of the key file important? Sure, I could have copied your entire example, but then I would also end up with an application, that does exactly what your example does. Unfortunately, that's not what my customer needs ;-)

    Anyway: Thanks a lot! This was extremely helpful. Thanks for your patience! I think, we can close this.

    best regards

    Torsten 

Reply
  • Hi Vidar,

    the linker error above happens, when I use a different name for the external flash memory. Only, when I name that chip mx25r64, I do not get that linker error.

    Thanks for the example, but it doesn't build correctly (board is unknown). When I change the board to  `nrf5340dk/nrf5340/cpuapp` I get some configuration warnings:

    warning: SPI_NOR (defined at soc/gaisler/gr716a/Kconfig.defconfig:18, drivers/flash/Kconfig.nor:4)
    was assigned the value 'y' but got the value 'n'. Check these unsatisfied dependencies: ((FLASH &&
    SOC_GR716A) || (DT_HAS_JEDEC_SPI_NOR_ENABLED && FLASH))

    The `CONFIG_NORDIC_QSPI_NOR` configuration was explicitly set to `y`. Then I change the device name to `flash_ext: MT25QU01GBBB@0 `:

    &qspi {
        /*
         * Name of the device has to be mx25r64; Otherwise,
         * the driver is not found during linking
         */
    /*    mx25r64: mx25r6435f@0 {*/
        flash_ext: MT25QU01GBBB@0 {
            compatible = "nordic,qspi-nor";
            reg = < 0x0 >;
            writeoc = "pp4io";
            readoc = "read4io";
            sck-frequency = < 90000000 >;
            jedec-id = [ 20 BB 21 ];
            sfdp-bfp = [ E5 20 F1 FF FF FF FF 03 44 EB 08 6B 08 3B 04 BB EE FF FF FF FF FF 00 FF FF FF 00 FF 0C 20 0F 52 10 D8 00 FF 23 72 F5 00 82 ED 04 CC 44 83 68 44 30 B0 30 B0 F7 C4 D5 5C 00 BE 29 FF F0 D0 FF FF ];
            size = < 0x8000000 >;
            has-dpd;
            t-enter-dpd = < 0x2710 >;
            t-exit-dpd = < 0x88b8 >;
        };
    };
    
    / {
        chosen {
    /*        nordic,pm-ext-flash = &mx25r64;*/
            nordic,pm-ext-flash = &flash_ext;
        };
    };
    

    I get an undefined symbol to `__device_dts_ord_142`.

    Yes, your example used `SB_CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y` and I even tried that setting and your keys on my course to find some configuration that builds. And as soon as it build, I changed it back to my keys and thus to the algorithm, I've picked.

    That's the major problem with examples. You never know, which bit is really important. Is the name of the key file important? Sure, I could have copied your entire example, but then I would also end up with an application, that does exactly what your example does. Unfortunately, that's not what my customer needs ;-)

    Anyway: Thanks a lot! This was extremely helpful. Thanks for your patience! I think, we can close this.

    best regards

    Torsten 

Children
  • Hi Torsten,

    Torsten Robitzki said:
    Thanks for the example, but it doesn't build correctly (board is unknown). When I change the board to  `nrf5340dk/nrf5340/cpuapp` I get some configuration warnings:

    Sorry, I see now that it is only compatible with the SPI NOR driver, not the QSPI NOR driver. This means that if you want to test it, you would have to place the external flash device on a SPI bus and use the `jedec,spi-nor` binding instead of "nordic,qspi-nor". The SPI flash sample works with QSPI, but it does not read the JDEC information.

    Torsten Robitzki said:
    That's the major problem with examples. You never know, which bit is really important. Is the name of the key file important? Sure, I could have copied your entire example, but then I would also end up with an application, that does exactly what your example does. Unfortunately, that's not what my customer needs ;-)

    I understand the challenges, and I hope this is something we can improve on. This is particularly a problem with the 53 series, as there are quite a few additional configuration options to handle multi-image DFU.

    Best regards,

    Vidar

Related