TF-M partition alignment assert within SPU might fail for some partition-manager computed configs

v2.3.0 of the sdk-nrf included this commit that checks for the alignment of the TF-M Non Secure partition (which hosts the `app` one) with CONFIG_NRF_SPU_FLASH_REGION_SIZE .

#define IS_ALIGNED_POW2(value, align) (((value) & ((align) - 1)) == 0)

#if !(IS_ALIGNED_POW2(PM_TFM_NONSECURE_ADDRESS, CONFIG_NRF_SPU_FLASH_REGION_SIZE))
#error "TF-M non-secure address start is not aligned on SPU region size"
#endif

For stock/most cases (eg. hello_world code), the assertion holds and the project compiles. 

The problem arouses when the partition_manager.py script outputs a layout solution in which the resulting PM_TFM_NONSECURE_ADDRESS becomes non-aligned. This has been my experience with the current project that I'm working on.

To temporarily mitigate this, I ended up taking out the alignment assertion check altogether. 

Is this a safe thing to do or is there any other better solution to this?

Thank you,

V

Parents
  • Hi,

     

    On the nRF5340, each flash protect region is 16kB aligned:

    https://infocenter.nordicsemi.com/topic/ps_nrf5340/spu.html?cp=4_0_0_6_31_1#flash_access_control

    If your partitions do not align on 16kB regions, you must disable the CONFIG_FPROTECT in addition to the change that you have already done.

     

    Is this a safe thing to do or is there any other better solution to this?

    Disabling the FPROTECT has its drawbacks, security-wise, so if possible; I would recommend that you keep FPROTECT enabled and rather align your partitions in pm_static.yml in such a way that it passes this specific test.

     

    Are you creating FOTA images for a product out in the field?

    Update 24th of March:

    My initial striked out comment is incorrect. This 16k (32k for nRF9160) alignment is based on the "app" region, which holds both the TFM image and the non-secure application.

    Mcuboot will see the TFM+non_secure application as one whole section. This means that all FOTA images can be dynamically aligned for TFM+non_secure-app, and thus be able to use FPROTECT. 

     

    Kind regards,

    Håkon

  • Thank you for the reply, Håkon!

    Yes, we are planning on doing fota-s, but have not yet shipped the initial version. We are striving to have FPROTECT on since the device is considered a high-security, critical, application.

    It would be nice if the partition_manage.py script would be aware of this alignment constraint and generate solutions accordingly. As it is now, I do see it causing issues for others: outputting a valid layout config while failing the SPU alignment guard.

  • Hi,

     

    3Nigma said:
    Yes, we are planning on doing fota-s, but have not yet shipped the initial version. We are striving to have FPROTECT on since the device is considered a high-security, critical, application.

    Could you share your pm_static.yml (or the build/partitions.yml) file?

     

    3Nigma said:
    It would be nice if the partition_manage.py script would be aware of this alignment constraint and generate solutions accordingly. As it is now, I do see it causing issues for others: outputting a valid layout config while failing the SPU alignment guard.

    I will report this internally, and make the developers aware of this.

     

    Kind regards,

    Håkon

  • Sure! Here is the partitions.yml file:

    EMPTY_0:
      address: 0xff00
      end_address: 0x10000
      placement:
        before:
        - mcuboot_pad
      region: flash_primary
      size: 0x100
    app:
      address: 0x20200
      end_address: 0x100000
      region: flash_primary
      size: 0xdfe00
    external_flash:
      address: 0x8f2000
      end_address: 0x1000000
      region: external_flash
      size: 0x70e000
    littlefs_storage:
      address: 0xf2000
      device: DT_CHOSEN(nordic_pm_ext_flash)
      end_address: 0x8f2000
      placement:
        before:
        - tfm_storage
        - end
      region: external_flash
      size: 0x800000
    mcuboot:
      address: 0x0
      end_address: 0xff00
      placement:
        before:
        - mcuboot_primary
      region: flash_primary
      size: 0xff00
    mcuboot_pad:
      address: 0x10000
      end_address: 0x10200
      placement:
        align:
          start: 0x4000
        before:
        - mcuboot_primary_app
      region: flash_primary
      size: 0x200
    mcuboot_primary:
      address: 0x10000
      end_address: 0x100000
      orig_span: &id001
      - mcuboot_pad
      - app
      - tfm
      region: flash_primary
      size: 0xf0000
      span: *id001
    mcuboot_primary_app:
      address: 0x10200
      end_address: 0x100000
      orig_span: &id002
      - app
      - tfm
      region: flash_primary
      size: 0xefe00
      span: *id002
    mcuboot_secondary:
      address: 0x0
      device: DT_CHOSEN(nordic_pm_ext_flash)
      end_address: 0xf0000
      placement:
        align:
          start: 0x4
      region: external_flash
      share_size:
      - mcuboot_primary
      size: 0xf0000
    mcuboot_sram:
      address: 0x20000000
      end_address: 0x20008000
      orig_span: &id003
      - tfm_sram
      region: sram_primary
      size: 0x8000
      span: *id003
    otp:
      address: 0xff8100
      end_address: 0xff83fc
      region: otp
      size: 0x2fc
    rpmsg_nrf53_sram:
      address: 0x20070000
      end_address: 0x20080000
      placement:
        before:
        - end
      region: sram_primary
      size: 0x10000
    settings_storage:
      address: 0xf0000
      device: DT_CHOSEN(nordic_pm_ext_flash)
      end_address: 0xf2000
      inside:
      - nonsecure_storage
      placement:
        before:
        - tfm_storage
        - end
      region: external_flash
      size: 0x2000
    sram_nonsecure:
      address: 0x20008000
      end_address: 0x20080000
      orig_span: &id004
      - sram_primary
      - rpmsg_nrf53_sram
      region: sram_primary
      size: 0x78000
      span: *id004
    sram_primary:
      address: 0x20008000
      end_address: 0x20070000
      region: sram_primary
      size: 0x68000
    sram_secure:
      address: 0x20000000
      end_address: 0x20008000
      orig_span: &id005
      - tfm_sram
      region: sram_primary
      size: 0x8000
      span: *id005
    tfm:
      address: 0x10200
      end_address: 0x20200
      inside:
      - mcuboot_primary_app
      placement:
        before:
        - app
      region: flash_primary
      size: 0x10000
    tfm_nonsecure:
      address: 0x20200
      end_address: 0x100000
      orig_span: &id006
      - app
      region: flash_primary
      size: 0xdfe00
      span: *id006
    tfm_secure:
      address: 0x10000
      end_address: 0x20200
      orig_span: &id007
      - mcuboot_pad
      - tfm
      region: flash_primary
      size: 0x10200
      span: *id007
    tfm_sram:
      address: 0x20000000
      end_address: 0x20008000
      inside:
      - sram_secure
      placement:
        after:
        - start
      region: sram_primary
      size: 0x8000
    

    Thank you once again,

    Take care,

    V

  • Hi,

     

    It looks like your mcuboot partition is generated with 0x100 bytes less than normal:

    EMPTY_0:
      address: 0xff00
      end_address: 0x10000
      placement:
        before:
        - mcuboot_pad
      region: flash_primary
      size: 0x100
    mcuboot:
      address: 0x0
      end_address: 0xff00
      placement:
        before:
        - mcuboot_primary
      region: flash_primary
      size: 0xff00

     

    Could you try to copy the my_app/build-folder/partitions.yml to my_app/pm_static.yml?

    Then make the following change by removing EMPTY_0 and adjusting mcuboot to 0x10000?

    mcuboot:
      address: 0x0
      end_address: 0x10000
      placement:
        before:
        - mcuboot_primary
      region: flash_primary
      size: 0x10000

     

    Kind regards,

    Håkon

  • Thank you for such a quick response and looking into it, Håkon .

    As for your suggestion (and in my defense), I was playing with CONFIG_PM_PARTITION_SIZE_MCUBOOT a while back and forgot about it. Did what you suggested and now there is no EMPTY_0 region. Thank you.

      external_flash (0x1000000 - 16384kB):
    +-----------------------------------------------+
    | 0x0: mcuboot_secondary (0xf0000 - 960kB)      |
    | 0xf0000: settings_storage (0x2000 - 8kB)      |
    | 0xf2000: littlefs_storage (0x800000 - 8192kB) |
    | 0x8f2000: external_flash (0x70e000 - 7224kB)  |
    +-----------------------------------------------+
    
      flash_primary (0x100000 - 1024kB):
    +--------------------------------------------------+
    | 0x0: mcuboot (0x10000 - 64kB)                    |
    +---0x10000: mcuboot_primary (0xf0000 - 960kB)-----+
    +---0x10000: tfm_secure (0x10200 - 64kB)-----------+
    | 0x10000: mcuboot_pad (0x200 - 512B)              |
    +---0x10200: mcuboot_primary_app (0xefe00 - 959kB)-+
    | 0x10200: tfm (0x10000 - 64kB)                    |
    +---0x20200: tfm_nonsecure (0xdfe00 - 895kB)-------+
    | 0x20200: app (0xdfe00 - 895kB)                   |
    +--------------------------------------------------+
    
      otp (0x2fc - 764B):
    +------------------------------+
    | 0xff8100: otp (0x2fc - 764B) |
    +------------------------------+
    
      sram_primary (0x80000 - 512kB):
    +------------------------------------------------+
    +---0x20000000: mcuboot_sram (0x8000 - 32kB)-----+
    +---0x20000000: sram_secure (0x8000 - 32kB)------+
    | 0x20000000: tfm_sram (0x8000 - 32kB)           |
    +---0x20008000: sram_nonsecure (0x78000 - 480kB)-+
    | 0x20008000: sram_primary (0x68000 - 416kB)     |
    | 0x20070000: rpmsg_nrf53_sram (0x10000 - 64kB)  |
    +------------------------------------------------+
    
     CPUNET flash_primary (0x40000 - 256kB):
    +----------------------------------------+
    +---0x1000000: app (0x40000 - 256kB)-----+
    | 0x1000000: hci_rpmsg (0x40000 - 256kB) |
    +----------------------------------------+
    
     CPUNET sram_primary (0x10000 - 64kB):
    +-------------------------------------------+
    | 0x21000000: sram_primary (0x10000 - 64kB) |
    +-------------------------------------------+

    And here is the new partitions.yml file:

    app:
      address: 0x20200
      end_address: 0x100000
      region: flash_primary
      size: 0xdfe00
    external_flash:
      address: 0x8f2000
      end_address: 0x1000000
      region: external_flash
      size: 0x70e000
    littlefs_storage:
      address: 0xf2000
      device: DT_CHOSEN(nordic_pm_ext_flash)
      end_address: 0x8f2000
      placement:
        before:
        - tfm_storage
        - end
      region: external_flash
      size: 0x800000
    mcuboot:
      address: 0x0
      end_address: 0x10000
      placement:
        before:
        - mcuboot_primary
      region: flash_primary
      size: 0x10000
    mcuboot_pad:
      address: 0x10000
      end_address: 0x10200
      placement:
        align:
          start: 0x4000
        before:
        - mcuboot_primary_app
      region: flash_primary
      size: 0x200
    mcuboot_primary:
      address: 0x10000
      end_address: 0x100000
      orig_span: &id001
      - mcuboot_pad
      - app
      - tfm
      region: flash_primary
      size: 0xf0000
      span: *id001
    mcuboot_primary_app:
      address: 0x10200
      end_address: 0x100000
      orig_span: &id002
      - app
      - tfm
      region: flash_primary
      size: 0xefe00
      span: *id002
    mcuboot_secondary:
      address: 0x0
      device: DT_CHOSEN(nordic_pm_ext_flash)
      end_address: 0xf0000
      placement:
        align:
          start: 0x4
      region: external_flash
      share_size:
      - mcuboot_primary
      size: 0xf0000
    mcuboot_sram:
      address: 0x20000000
      end_address: 0x20008000
      orig_span: &id003
      - tfm_sram
      region: sram_primary
      size: 0x8000
      span: *id003
    otp:
      address: 0xff8100
      end_address: 0xff83fc
      region: otp
      size: 0x2fc
    rpmsg_nrf53_sram:
      address: 0x20070000
      end_address: 0x20080000
      placement:
        before:
        - end
      region: sram_primary
      size: 0x10000
    settings_storage:
      address: 0xf0000
      device: DT_CHOSEN(nordic_pm_ext_flash)
      end_address: 0xf2000
      inside:
      - nonsecure_storage
      placement:
        before:
        - tfm_storage
        - end
      region: external_flash
      size: 0x2000
    sram_nonsecure:
      address: 0x20008000
      end_address: 0x20080000
      orig_span: &id004
      - sram_primary
      - rpmsg_nrf53_sram
      region: sram_primary
      size: 0x78000
      span: *id004
    sram_primary:
      address: 0x20008000
      end_address: 0x20070000
      region: sram_primary
      size: 0x68000
    sram_secure:
      address: 0x20000000
      end_address: 0x20008000
      orig_span: &id005
      - tfm_sram
      region: sram_primary
      size: 0x8000
      span: *id005
    tfm:
      address: 0x10200
      end_address: 0x20200
      inside:
      - mcuboot_primary_app
      placement:
        before:
        - app
      region: flash_primary
      size: 0x10000
    tfm_nonsecure:
      address: 0x20200
      end_address: 0x100000
      orig_span: &id006
      - app
      region: flash_primary
      size: 0xdfe00
      span: *id006
    tfm_secure:
      address: 0x10000
      end_address: 0x20200
      orig_span: &id007
      - mcuboot_pad
      - tfm
      region: flash_primary
      size: 0x10200
      span: *id007
    tfm_sram:
      address: 0x20000000
      end_address: 0x20008000
      inside:
      - sram_secure
      placement:
        after:
        - start
      region: sram_primary
      size: 0x8000
    

    Unfortunately, as you might expect, I'm still getting the "TF-M non-secure address start is not aligned on SPU region size" compile-time error.

    Thank you,

    V

Reply
  • Thank you for such a quick response and looking into it, Håkon .

    As for your suggestion (and in my defense), I was playing with CONFIG_PM_PARTITION_SIZE_MCUBOOT a while back and forgot about it. Did what you suggested and now there is no EMPTY_0 region. Thank you.

      external_flash (0x1000000 - 16384kB):
    +-----------------------------------------------+
    | 0x0: mcuboot_secondary (0xf0000 - 960kB)      |
    | 0xf0000: settings_storage (0x2000 - 8kB)      |
    | 0xf2000: littlefs_storage (0x800000 - 8192kB) |
    | 0x8f2000: external_flash (0x70e000 - 7224kB)  |
    +-----------------------------------------------+
    
      flash_primary (0x100000 - 1024kB):
    +--------------------------------------------------+
    | 0x0: mcuboot (0x10000 - 64kB)                    |
    +---0x10000: mcuboot_primary (0xf0000 - 960kB)-----+
    +---0x10000: tfm_secure (0x10200 - 64kB)-----------+
    | 0x10000: mcuboot_pad (0x200 - 512B)              |
    +---0x10200: mcuboot_primary_app (0xefe00 - 959kB)-+
    | 0x10200: tfm (0x10000 - 64kB)                    |
    +---0x20200: tfm_nonsecure (0xdfe00 - 895kB)-------+
    | 0x20200: app (0xdfe00 - 895kB)                   |
    +--------------------------------------------------+
    
      otp (0x2fc - 764B):
    +------------------------------+
    | 0xff8100: otp (0x2fc - 764B) |
    +------------------------------+
    
      sram_primary (0x80000 - 512kB):
    +------------------------------------------------+
    +---0x20000000: mcuboot_sram (0x8000 - 32kB)-----+
    +---0x20000000: sram_secure (0x8000 - 32kB)------+
    | 0x20000000: tfm_sram (0x8000 - 32kB)           |
    +---0x20008000: sram_nonsecure (0x78000 - 480kB)-+
    | 0x20008000: sram_primary (0x68000 - 416kB)     |
    | 0x20070000: rpmsg_nrf53_sram (0x10000 - 64kB)  |
    +------------------------------------------------+
    
     CPUNET flash_primary (0x40000 - 256kB):
    +----------------------------------------+
    +---0x1000000: app (0x40000 - 256kB)-----+
    | 0x1000000: hci_rpmsg (0x40000 - 256kB) |
    +----------------------------------------+
    
     CPUNET sram_primary (0x10000 - 64kB):
    +-------------------------------------------+
    | 0x21000000: sram_primary (0x10000 - 64kB) |
    +-------------------------------------------+

    And here is the new partitions.yml file:

    app:
      address: 0x20200
      end_address: 0x100000
      region: flash_primary
      size: 0xdfe00
    external_flash:
      address: 0x8f2000
      end_address: 0x1000000
      region: external_flash
      size: 0x70e000
    littlefs_storage:
      address: 0xf2000
      device: DT_CHOSEN(nordic_pm_ext_flash)
      end_address: 0x8f2000
      placement:
        before:
        - tfm_storage
        - end
      region: external_flash
      size: 0x800000
    mcuboot:
      address: 0x0
      end_address: 0x10000
      placement:
        before:
        - mcuboot_primary
      region: flash_primary
      size: 0x10000
    mcuboot_pad:
      address: 0x10000
      end_address: 0x10200
      placement:
        align:
          start: 0x4000
        before:
        - mcuboot_primary_app
      region: flash_primary
      size: 0x200
    mcuboot_primary:
      address: 0x10000
      end_address: 0x100000
      orig_span: &id001
      - mcuboot_pad
      - app
      - tfm
      region: flash_primary
      size: 0xf0000
      span: *id001
    mcuboot_primary_app:
      address: 0x10200
      end_address: 0x100000
      orig_span: &id002
      - app
      - tfm
      region: flash_primary
      size: 0xefe00
      span: *id002
    mcuboot_secondary:
      address: 0x0
      device: DT_CHOSEN(nordic_pm_ext_flash)
      end_address: 0xf0000
      placement:
        align:
          start: 0x4
      region: external_flash
      share_size:
      - mcuboot_primary
      size: 0xf0000
    mcuboot_sram:
      address: 0x20000000
      end_address: 0x20008000
      orig_span: &id003
      - tfm_sram
      region: sram_primary
      size: 0x8000
      span: *id003
    otp:
      address: 0xff8100
      end_address: 0xff83fc
      region: otp
      size: 0x2fc
    rpmsg_nrf53_sram:
      address: 0x20070000
      end_address: 0x20080000
      placement:
        before:
        - end
      region: sram_primary
      size: 0x10000
    settings_storage:
      address: 0xf0000
      device: DT_CHOSEN(nordic_pm_ext_flash)
      end_address: 0xf2000
      inside:
      - nonsecure_storage
      placement:
        before:
        - tfm_storage
        - end
      region: external_flash
      size: 0x2000
    sram_nonsecure:
      address: 0x20008000
      end_address: 0x20080000
      orig_span: &id004
      - sram_primary
      - rpmsg_nrf53_sram
      region: sram_primary
      size: 0x78000
      span: *id004
    sram_primary:
      address: 0x20008000
      end_address: 0x20070000
      region: sram_primary
      size: 0x68000
    sram_secure:
      address: 0x20000000
      end_address: 0x20008000
      orig_span: &id005
      - tfm_sram
      region: sram_primary
      size: 0x8000
      span: *id005
    tfm:
      address: 0x10200
      end_address: 0x20200
      inside:
      - mcuboot_primary_app
      placement:
        before:
        - app
      region: flash_primary
      size: 0x10000
    tfm_nonsecure:
      address: 0x20200
      end_address: 0x100000
      orig_span: &id006
      - app
      region: flash_primary
      size: 0xdfe00
      span: *id006
    tfm_secure:
      address: 0x10000
      end_address: 0x20200
      orig_span: &id007
      - mcuboot_pad
      - tfm
      region: flash_primary
      size: 0x10200
      span: *id007
    tfm_sram:
      address: 0x20000000
      end_address: 0x20008000
      inside:
      - sram_secure
      placement:
        after:
        - start
      region: sram_primary
      size: 0x8000
    

    Unfortunately, as you might expect, I'm still getting the "TF-M non-secure address start is not aligned on SPU region size" compile-time error.

    Thank you,

    V

Children
  • Hi,

     

    Thank you for your patience in this matter.

    I have been able to recreate the issue with your pm_static.yml, and as you mention; it is related to the 0x200 offset (ie. after the ISR vector table) in the "tfm_nonsecure" region:

    grep -r PM_TFM_NONSECURE_ADDRESS
    zephyr/include/generated/pm_config.h:#define PM_TFM_NONSECURE_ADDRESS 0x20200
    pm.config:PM_TFM_NONSECURE_ADDRESS=0x20200
    

    Thank you very much for making us aware of this issue. This is highly appreciated.

    I was able to see this issue when using matter/light_bulb, and building for v2.2.0 and v2.3.0. The partitions.yml generated for v2.2.0 has a +0x200 offset in the non-secure partitions, while the v2.3.0 generated build does not have this. 

    Could you try a manual workaround to the issue, which is to change the "app" and "tfm_nonsecure" offset and size?

    Here's an example specific for your pm_static.yml:

    app:
      address: 0x20000
      end_address: 0x100000
      region: flash_primary
      size: 0xe0000
    
    tfm_nonsecure:
      address: 0x20000
      end_address: 0x100000
      orig_span: &id006
      - app
      region: flash_primary
      size: 0xe0000
      span: *id006

     

     

    Kind regards,

    Håkon

  • It will be a bit difficult, but I will give it a try with pm_static and come back to you, Håkon!

    Thank you soo much for looking into it!

    Best wishes,

    V

  • Hi V,

     

    Let me know if you run into any issues.

    I just had a talk with the tfm-team, and they assured me that it is a bug in the first place that the partitions were offset with 0x200, and the fix is to manually "port" the pm_static.yml file, similar to how it was done here with the thingy91 pm_static file:

    https://github.com/nrfconnect/sdk-nrf/commit/e736590c05bcb806c3d8a86e1629d2c0ec85a383#diff-55fb0a1775752c61c872a06f6b7aa14df324356f352ad7c73210531e43c672ec

     

    Another alternative can be to generate a new build on ncs v2.3.0, without the "ncs v2.2.0 pm_static.yml", and copy build-folder/partitions.yml to pm_static.yml and conform it to your expected layout.

     

    I have an action here to properly highlight and document this, either as a migration guide or similar.

     

    Kind regards,

    Håkon

  • Hi Håkon,

    Unfortunately, the pm_static.yml override doesn't seam to work. It looks like the kernel is faulting immediately after entering mcuboot so I don't quite know what's happening there and I don't have the proper time to investigate.

    For now, we'll just go with cloning the sdk-nrf repo and removing the PSU assert.c check via a commit + referencing our own, patched, sdk-nrf module when 'whest update'-ing. We'll plan on coming back to this, as time permits, and try to manually align it. If upstream won't do it first, that is.

    I have found another issue with the partition-manager when resolving the settings partition (in some scenario). I'll open another ticket for this.

    Thank you once again, Håkon!

    Best wishes,

    V

Related