Flash Partition Management with Trusted Firmware-M

Backround: We are planning to use TF-M with a two-stage bootloader (NSIB & MCUBoot) using dual-slots for secure and non-secure images. We need to support configurable fixed flash partitions (i.e. for event or configuration storage) and would like to retain the option to use an external flash in the future.

I have read through the nRF Connect SDK documentation, however it is not clear to me how the Partition Managed is used to configure fixed flash partitions for targets using TF-M. Could you please provide an example partition configuration on the nRF9160 (using internal flash) with: dual-slots for secure / non-secure images, secure storage (i.e. certificates), event storage (for telemetry) and configuration?

  • These partitions are defined in pm.yml files around the SDK.
    Specifically here (subsystems), this(NSIB) and this(MCUboot).

    Mark that there are differences between "span" and "placament". "Span" overlaps other partitions, while "placement" has a specific place in code. "Span" is thus mostly to describe sets of other partitions.

    • app: The "app" is where the zephyr application lives. This is the default partition and is always automatically generated by the partition manager.
    • app_image [span]: NSIB uses this when there is single bootloader. I don't think this one is used for dual bootloaders, but I might have missed some subtlety. For NSIB only, this is the address NSIB will boot to after the bootloader I think.
    • mcuboot_pad [placement]: MCUboot needs to store some metadata per image. Size 0x200. You see 0x200 repeat in the offsets right. Could more clearly have been named "mcuboot_primary_pad" to match the below name.
    • mcuboot_primary_app [span]: In your case, this overlaps with "app". But if we got direct-xip mode for MCUboot, we want two different app partitions, so then we also will have mcuboot_secondary_app. These have the address mcuboot will boot to after the bootloader.
    • mcuboot_primary [span]: We want to know the whole MCUboot primary (app + pad) to be under one. The full DFU binary goes into here, cause that has both image and metadata.
    • mcuboot_secondary [placement]: When updating the application, you want to swap it in. MCUboot secondary is generally for this.
    • tfm [placement]: The tfm application. This is code that runs, just as the app. Must be just before tha app.
    • tfm_secure [span] + tfm_nonsecure [span]: With TF-M, we want to do separation of SPE and NSPE Processing environments. So we create partitions so we know which to make S flash and which to make NS flash.
      • tfm_secure overlaps mcuboot_pad and tfm.
      • Note: Mark that tfm_nonsecure and tfm are updated by the MCUboot, os these are overlapped by mcuboot_primary

    I think I got this image correct, but feel free to check up against previously mentioned pm.yml files

    Regards,
    Sigurd Hellesvik

  • Is there any reason why the tfm (0x28200) partition is so large in the tfm_psa_template?

    When building the image it says it is only using 94 / 255 kB (37.16%) of FLASH. It seems excessive to allocate it such a partition, especially as the User & Zephyr code can grow to be quite large.

    Can the tfm and app partition sizes change after DFU?

  • vytautas said:
    Can the tfm and app partition sizes change after DFU?

    While indeed we have a Static partition requirement for DFU, this requirement is for bootloader and DFU partitions. The important thing is that where MCUboot boots to and where the DFU goes into does not change.
    Since tfm and app partitions are DFUed as one package, they can change sizes in comparison to each other. But mcuboot_primary_app, which they live inside, must stay the same. So sum size app+tfm must stay the same.

    vytautas said:
    Is there any reason why the tfm (0x28200) partition is so large in the tfm_psa_template?

    TF-M partition size is set here. As you see, it varies depending on TF-M features enabled.

    vytautas said:
    When building the image it says it is only using 94 / 255 kB (37.16%) of FLASH. It seems excessive to allocate it such a partition, especially as the User & Zephyr code can grow to be quite large.

    You are free to resize TF-M by configuring CONFIG_PM_PARTITION_SIZE_TFM yourself, and make this closer to 100%.
    It is also possible to disable features for TF-M, but my experience is that minimizing TF-M size can be tricky.

  • Sigurd Hellesvik said:
    You are free to resize TF-M by configuring CONFIG_PM_PARTITION_SIZE_TFM yourself, and make this closer to 100%.
    It is also possible to disable features for TF-M, but my experience is that minimizing TF-M size can be tricky.

    Assuming the partition size isn’t chosen arbitrarily, I’m guessing the compiler excludes unused TF-M features, resulting in the low memory usage I'm seeing with this sample. Is this correct?

    Also, looking closer at the partitioning, it is not clear where pending MCUBoot updates are stored. For instance, if updates are saved to mcuboot_secondary (0x88000), it may not leave sufficient space for the primary application (app + tfm). The only alternative I see is that the update is staged directly to S0 or S1 partition, however I would assume these flash regions aren't arbitrarily accessible and are protected by TF-M. Furthermore, if they are staged directly to those partitions, how does the application determine which slot to overwrite—say, if the current bootable image is in S1? Could you clarify this?

    PS. I don't think we've shared confidential information in this ticket. I think the information shared by you would be useful to others as well. Are you okay with making this ticket Public?

  • vytautas said:
    PS. I don't think we've shared confidential information in this ticket. I think the information shared by you would be useful to others as well. Are you okay with making this ticket Public?

    Excellent idea! I will make it public.

    vytautas said:
    Assuming the partition size isn’t chosen arbitrarily, I’m guessing the compiler excludes unused TF-M features, resulting in the low memory usage I'm seeing with this sample. Is this correct?

    Im gonna stop you on the assumption. As yoiu can see from Kconfig.tfm.pm, the size is only optimized for CONFIG_TFM_PROFILE_TYPE_MINIMAL. For all other TF-M profiles we default it to the number 0x40000. (depending on a couple of other tings such as bootloaders, but still).

    I think we just chose something that will work if we enable all features for TF-M.

    In short: We have not yet optimized non-minimal TF-M profiles, and leave optimizing partition sizes up to the user.

    vytautas said:
    For instance, if updates are saved to mcuboot_secondary (0x88000)

    MCUboot require that mcuboot_primary and mcuboot_secondary have the same size. This way, you can always fit the uptate for mcuboot_primary into mcuboot_secondary.

    vytautas said:
    The only alternative I see is that the update is staged directly to S0 or S1 partition

    S0 and S1 are slots where the mcuboot bootloader lives. They are only used for MCUboot, and for updating MCUboot.

Related