Configuring pm_static.yml when porting from SPM to TFM

Hello,

I'm working on updating my copy of the nRF Connect SDK from 1.7.0 to 2.4.2. My project runs on an nRF9160 so I had SPM configured for my project and now I need to use TFM instead. To do that, I'm following these instructions: https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/security/tfm.html#ug-tfm-migrate. However, I get an error during build configuration from the partition manager saying that there are gaps in my partitions:

Partition manager failed: Incorrect amount of gaps found in static configuration. There must be exactly one gap in the static configuration to support placing the dynamic partitions (such as 'app').
Gaps found (2):0x20000000-0x20010000 0x200144e8-0x20040000 The most common solution to this problem is to fill the smallest of these gaps with statically defined partition(s) until there is only one gap left.
Alternatively re-order the already defined static partitions so that only one gap remains.

I'm not finding any gaps in my file, and I'm changing over the names as instructed. Here's my new pm_static.yml file

app:
  address: 0x1c200
  end_address: 0xfa000
  region: flash_primary
  size: 0xdde00
external_flash:
  address: 0xf2000
  end_address: 0x400000
  placement:
    after:
    - mcuboot_secondary
  region: external_flash
  size: 0x30e000
mcuboot:
  address: 0x0
  end_address: 0xc000
  placement:
    before:
    - mcuboot_primary
  region: flash_primary
  size: 0xc000
mcuboot_pad:
  address: 0xc000
  # end_address: 0xc200
  placement:
    before:
    - mcuboot_primary_app
  region: flash_primary
  size: 0x0
mcuboot_primary:
  address: 0xc000
  end_address: 0xfe000
  orig_span: &id001
  - tfm
  - mcuboot_pad
  - app
  region: flash_primary
  size: 0xf2000
  span: *id001
mcuboot_primary_app:
  address: 0xc200
  end_address: 0xfe000
  orig_span: &id002
  - app
  - tfm
  region: flash_primary
  size: 0xf1e00
  span: *id002
mcuboot_secondary:
  address: 0x0
  device: MX25L3
  end_address: 0xf2000
  placement:
    align:
      start: 0x0
  region: external_flash
  size: 0xf2000
nrf_modem_lib_ctrl:
  address: 0x20010000
  end_address: 0x200104e8
  inside:
  - sram_nonsecure
  placement:
    after:
    - start
  region: sram_primary
  size: 0x4e8
nrf_modem_lib_rx:
  address: 0x200124e8
  end_address: 0x200144e8
  inside:
  - sram_nonsecure
  placement:
    after:
    - nrf_modem_lib_tx
  region: sram_primary
  size: 0x2000
nrf_modem_lib_sram:
  address: 0x20010000
  end_address: 0x200144e8
  orig_span: &id003
  - nrf_modem_lib_ctrl
  - nrf_modem_lib_tx
  - nrf_modem_lib_rx
  region: sram_primary
  size: 0x44e8
  span: *id003
nrf_modem_lib_tx:
  address: 0x200104e8
  end_address: 0x200124e8
  inside:
  - sram_nonsecure
  placement:
    after:
    - nrf_modem_lib_ctrl
  region: sram_primary
  size: 0x2000
otp:
  address: 0xff8108
  end_address: 0xff83fc
  region: otp
  size: 0x2f4
tfm:
  address: 0xc000
  end_address: 0x1c200
  inside:
  - mcuboot_primary_app
  placement:
    before:
    - app
  region: flash_primary
  size: 0x10200
tfm_secure:
  address: 0xc000
  size: 0x10000
  span: [mcuboot_pad, tfm]
tfm_nonsecure:
  address: 0x1c200
  size: 0xdde00
  span: [app]
sram_nonsecure:
  address: 0x20010000
  end_address: 0x20040000
  orig_span: &id004
  - sram_primary
  - nrf_modem_lib_ctrl
  - nrf_modem_lib_tx
  - nrf_modem_lib_rx
  region: sram_primary
  size: 0x30000
  span: *id004
sram_primary:
  address: 0x200144e8
  end_address: 0x20040000
  region: sram_primary
  size: 0x2bb18
sram_secure:
  address: 0x20000000
  end_address: 0x20010000
  orig_span: &id005
  region: sram_primary
  size: 0x10000
  span: *id005
lwm2m_carrier:
  address: 0xfa000
  size: 0x4000
  inside:
  - tfm_nonsecure
settings_storage:
  address: 0xfe000
  end_address: 0x100000
  placement:
    before:
    - end
  region: flash_primary
  inside:
  - tfm_nonsecure
  size: 0x2000

compared to my old one:

app:
  address: 0x1c200
  end_address: 0xfa000
  region: flash_primary
  size: 0xdde00
external_flash:
  address: 0xf2000
  end_address: 0x400000
  placement:
    after:
    - mcuboot_secondary
  region: external_flash
  size: 0x30e000
mcuboot:
  address: 0x0
  end_address: 0xc000
  placement:
    before:
    - mcuboot_primary
  region: flash_primary
  size: 0xc000
mcuboot_pad:
  address: 0xc000
  end_address: 0xc200
  placement:
    before:
    - mcuboot_primary_app
  region: flash_primary
  size: 0x200
mcuboot_primary:
  address: 0xc000
  end_address: 0xfe000
  orig_span: &id001
  - spm
  - mcuboot_pad
  - app
  region: flash_primary
  size: 0xf2000
  span: *id001
mcuboot_primary_app:
  address: 0xc200
  end_address: 0xfe000
  orig_span: &id002
  - app
  - spm
  region: flash_primary
  size: 0xf1e00
  span: *id002
mcuboot_secondary:
  address: 0x0
  device: MX25L3
  end_address: 0xf2000
  placement:
    align:
      start: 0x0
  region: external_flash
  size: 0xf2000
nrf_modem_lib_ctrl:
  address: 0x20010000
  end_address: 0x200104e8
  inside:
  - sram_nonsecure
  placement:
    after:
    - spm_sram
    - start
  region: sram_primary
  size: 0x4e8
nrf_modem_lib_rx:
  address: 0x200124e8
  end_address: 0x200144e8
  inside:
  - sram_nonsecure
  placement:
    after:
    - nrf_modem_lib_tx
  region: sram_primary
  size: 0x2000
nrf_modem_lib_sram:
  address: 0x20010000
  end_address: 0x200144e8
  orig_span: &id003
  - nrf_modem_lib_ctrl
  - nrf_modem_lib_tx
  - nrf_modem_lib_rx
  region: sram_primary
  size: 0x44e8
  span: *id003
nrf_modem_lib_tx:
  address: 0x200104e8
  end_address: 0x200124e8
  inside:
  - sram_nonsecure
  placement:
    after:
    - nrf_modem_lib_ctrl
  region: sram_primary
  size: 0x2000
otp:
  address: 0xff8108
  end_address: 0xff83fc
  region: otp
  size: 0x2f4
spm:
  address: 0xc200
  end_address: 0x1c200
  inside:
  - mcuboot_primary_app
  placement:
    before:
    - app
  region: flash_primary
  size: 0x10000
spm_sram:
  address: 0x20000000
  end_address: 0x20010000
  inside:
  - sram_secure
  placement:
    after:
    - start
  region: sram_primary
  size: 0x10000
sram_nonsecure:
  address: 0x20010000
  end_address: 0x20040000
  orig_span: &id004
  - sram_primary
  - nrf_modem_lib_ctrl
  - nrf_modem_lib_tx
  - nrf_modem_lib_rx
  region: sram_primary
  size: 0x30000
  span: *id004
sram_primary:
  address: 0x200144e8
  end_address: 0x20040000
  region: sram_primary
  size: 0x2bb18
sram_secure:
  address: 0x20000000
  end_address: 0x20010000
  orig_span: &id005
  - spm_sram
  region: sram_primary
  size: 0x10000
  span: *id005
lwm2m_carrier:
  address: 0xfa000
  size: 0x4000
settings_storage:
  address: 0xfe000
  end_address: 0x100000
  placement:
    before:
    - end
  region: flash_primary
  size: 0x2000

Does anyone see anything glaringly wrong or have any tips?

  • Hi esisk,

    It seems you have made lots of progress. That's great.

    Regarding the partition configuration, if you still have concern, can you share the partition manager report from the original 1.7.1 setup and the current setup? It helps make it easier to check if everything is correct.

    esisk said:
    In the console, "false" is getting printed so I know that the function should return it just doesn't. Which makes me realize that I had to reduce CONFIG_MAIN_STACK_SIZE to 5000 in order to build the project with logging, so the stack must have overflowed at some point. However, setting it back to CONFIG_MAIN_STACK_SIZE=10240 overflows the RAM allocated for MCUBoot by 600ish bytes when building. Setting the stack size to anything lower than 10240 results in my app not running and I can't build the project now with the original stack size.

    In a setting with secure domain, MCUboot is limited to the secure RAM region. If the logging is only for debugging, you can use CONFIG_MCUBOOT_USE_ALL_AVAILABLE_RAM to help give it more RAM to work. Once we figure out the issue, CONFIG_MCUBOOT_USE_ALL_AVAILABLE_RAM can be disabled again.

  • After doing some further debugging, it seems that available RAM is not the issue. I've now tracked the stall down to bootutil_img_hash called in bootutil_img_validate. Maybe there is something that's changed in terms of MCUBoot performing crypto calls in NCS 2.x.x. Also, did the public key used to verify images change when the SDK was updated, or do I need to somehow link the public key to the private signing key that I'm using when re-installing the SDK? I'll include all my configuration files for clarity.

    curr_cfg.zip

    Edit:

    Tried building with the default signing key provided with the SDK and I run into the same stall, so the key is most likely not the issue.

    Edit 2:

    Interesting find... I programmed the board using the configuration setup included in the zip file I attached here and ran into the same stall. However, if I do a pin reset of the board, I see that my application starts up just fine. Any ideas as to why that could be?

    Edit 3:

    After doing more debugging, I discovered that for some reason, logging stopped working after a bit in MCUBoot. So the program was never actually getting stuck. I just replaced calls to BOOT_LOG_INF with printf and I got more info:

    00> Here[00:00:00.489,593] <inf> mcuboot: Starting bootloader
    00> [00:00:00.490,325] <inf> mcuboot: Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
    00> [00:00:00.490,661] <inf> mcuboot: Secondary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
    00> [00:00:00.490,661] <inf> mcuboot: Boot source: none
    00> [00:00:00.491,149] <inf> mcuboot: Swap type: none
    00> here12here14Bootloader chainload address offset: 0xc000Jumping to the first image slot

    MCUBoot is attempting to boot into the image. However, I'm still seeing nothing being logged by my application. That leads me to believe that either the address it's booting into is incorrect or TFM is getting stuck. The address it's booting into is 0xc000 which corresponds to mcuboot_pad as outlined in my pm_static.yml. Shouldn't it be using 0xc200 as the address? And is there a way to log TFM output via RTT?

  • The public key is regenerated from the private key whenever you build the application. However, that should not be an issue as long as the private key remain the same.

    esisk said:
    MCUBoot is attempting to boot into the image. However, I'm still seeing nothing being logged by my application. That leads me to believe that either the address it's booting into is incorrect or TFM is getting stuck. The address it's booting into is 0xc000 which corresponds to mcuboot_pad as outlined in my pm_static.yml. Shouldn't it be using 0xc200 as the address? And is there a way to log TFM output via RTT?

    This is good progress. Given your finding, I agree with your conclusion.

    Adding logging from TF-M is possible, but only via UART. Please refer to this page: Running applications with Trusted Firmware-M (nordicsemi.com).

    I think it might be worth it to try this with a very minimal setup. Perhaps use the Hello World sample, and adding just MCUboot, the MCUboot relevant Kconfig, and the current pm_static.yml. If this setup works, then it would indicate the issue is with the application.

    Following a similar logic, please also try compiling the application without MCUboot to see if it has any issue running.

  • The public key is regenerated from the private key whenever you build the application. However, that should not be an issue as long as the private key remain the same.

    Good to know, I won't consider this as a possible problem.

    I think it might be worth it to try this with a very minimal setup. Perhaps use the Hello World sample, and adding just MCUboot, the MCUboot relevant Kconfig, and the current pm_static.yml. If this setup works, then it would indicate the issue is with the application.

    I've already made it to where my application is just an infinite while loop printing "Here" every 5 seconds once entering into main, so I doubt it'd be my application. But I will try a minimal setup with an out of the box sample and see if that works. I will also try running both my app and a sample app without MCUBoot. I'll work on this today and update you on my progress

  • Hey Hieu,

    Sorry for the delay, I've gotten sidetracked with other priorities. I just tried running my app without MCUBoot, and I'm not seeing anything being printed to the console. The app is an infinite while loop that prints "Hello World" every five seconds. I will try to build the application without TFM as well and see how that affects it.

    Edit 1:

    When trying to build a the hello_world sample from zephyr/samples, I get this error:

    /home/ethan/fw-dev/v2.4.2/nrf/lib/nrf_modem_lib/nrf_modem_lib.c:17:10: fatal error: pm_config.h: No such file or directory
       17 | #include <pm_config.h>

    Any ideas on how to fix this? I'm trying to just run something with only tfm and an app that prints hello world to the console with nothing else configured.

    Edit 2:

    When looking at some samples I see this config variable CONFIG_TFM_BL2, could you explain more what this does?

Related