Static Partition Alignment

Hi,

We have a few questions regarding the pm_static.yml file that's used for defining flash partitions in zephyr. 

Our main questions are regarding alignment; we've created a partition "device_details_partition" where we plan on writing configuration values at manufacturing using nrfjprog via an external nRF53DK. 

These values should be permanent for the lifecycle of the device and will only ever be read in the application firmware, never overwritten. "device_details_partition" needs to have static memory locations so we know where to write/read.

The "device_details_partition" is only 16 bytes long so we're unable to align it to 4kb, we've defined it as follows;

device_details_partition:
  address: 0xf3FF0  # New address, originally where user_partition started
  end_address: 0xf4000  # Size is 0x10
  region: flash_primary
  size: 0x10
Adding this partition has meant we've had to reduce the size of some other partitions including mcuboot_primary, mcuboot_primary_app and app.

Some questions we had about this implementation:
  1. Could having the size and end address of mcuboot_primary and mcuboot_primary_app not 4kb aligned cause any issues?
  2. Is there a better way we can create "device_details_partition"? A section of flash which can be flashed externally.

Below is our full pm_static.yml

user_partition: # NVS Storage
  address: 0xf6000  
  end_address: 0xf8000  
  placement:
    after:
    - settings_storage
  region: flash_primary
  size: 0x2000
device_details_partition:
  address: 0xf3FF0  # New address
  end_address: 0xf4000  # Size is 0x10
  region: flash_primary
  size: 0x10
app:
  address: 0x4c200
  end_address: 0xf3FF0 # Decreased by 0x10
  region: flash_primary
  size: 0xa7df0
external_flash:
  address: 0x128000
  end_address: 0x200000
  region: external_flash
  size: 0xd8000
mcuboot:
  address: 0x0
  end_address: 0xc000
  placement:
    before:
    - mcuboot_primary
  region: flash_primary
  size: 0xc000
mcuboot_pad:
  address: 0xc000
  end_address: 0xc200
  placement:
    align:
      start: 0x4000
    before:
    - mcuboot_primary_app
  region: flash_primary
  size: 0x200
mcuboot_primary:
  address: 0xc000
  end_address: 0xf3FF0 # Decreased by 0x10
  orig_span: &id001
  - mcuboot_pad
  - app
  - tfm
  region: flash_primary
  size: 0xe7FF0
  span: *id001
mcuboot_primary_1:
  address: 0x0
  device: nordic_ram_flash_controller
  end_address: 0x40000
  region: ram_flash
  size: 0x40000
mcuboot_primary_app:
  address: 0xc200
  end_address: 0xf3FF0 # Decreased by 0x10
  orig_span: &id002
  - app
  - tfm
  region: flash_primary
  size: 0xe7e00
  span: *id002
mcuboot_secondary:
  address: 0x0
  device: DT_CHOSEN(nordic_pm_ext_flash)
  end_address: 0xe8000
  placement:
    align:
      start: 0x4
  region: external_flash
  share_size:
  - mcuboot_primary
  size: 0xe8000
mcuboot_secondary_1:
  address: 0xe8000
  device: DT_CHOSEN(nordic_pm_ext_flash)
  end_address: 0x128000
  region: external_flash
  size: 0x40000
nonsecure_storage:
  address: 0xf4000  
  end_address: 0xf6000 
  orig_span: &id003
  - settings_storage
  region: flash_primary
  size: 0x2000 
  span: *id003
otp:
  address: 0xff8100
  end_address: 0xff83fc
  region: otp
  size: 0x2fc
pcd_sram:
  address: 0x20000000
  end_address: 0x20002000
  placement:
    before:
    - tfm_sram
  region: sram_primary
  size: 0x2000
ram_flash:
  address: 0x40000
  end_address: 0x40000
  region: ram_flash
  size: 0x0
rpmsg_nrf53_sram:
  address: 0x20070000
  end_address: 0x20080000
  placement:
    before:
    - end
  region: sram_primary
  size: 0x10000

settings_storage:
  address: 0xf4000  
  end_address: 0xf6000  
  inside:
  - nonsecure_storage
  placement:
    align:
      start: 0x4000
    before:
    - tfm_storage
    - end
  region: flash_primary
  size: 0x2000
sram_nonsecure:
  address: 0x2000fd70
  end_address: 0x20080000
  orig_span: &id004
  - sram_primary
  - rpmsg_nrf53_sram
  region: sram_primary
  size: 0x70290
  span: *id004
sram_primary:
  address: 0x2000fd70
  end_address: 0x20070000
  region: sram_primary
  size: 0x60290
sram_secure:
  address: 0x20000000
  end_address: 0x2000fd70
  orig_span: &id005
  - pcd_sram
  - tfm_sram
  region: sram_primary
  size: 0xfd70
  span: *id005
tfm:
  address: 0xc200
  end_address: 0x4c200
  inside:
  - mcuboot_primary_app
  placement:
    before:
    - app
  region: flash_primary
  size: 0x40000
tfm_its:
  address: 0xf8000
  end_address: 0xfa000
  inside:
  - tfm_storage
  placement:
    before:
    - tfm_otp_nv_counters
  region: flash_primary
  size: 0x2000
tfm_nonsecure:
  address: 0x4c200
  end_address: 0xf3FF0
  orig_span: &id006
  - app
  region: flash_primary
  size: 0xa7df0
  span: *id006
tfm_otp_nv_counters:
  address: 0xfa000
  end_address: 0xfc000
  inside:
  - tfm_storage
  placement:
    before:
    - tfm_ps
  region: flash_primary
  size: 0x2000
tfm_ps:
  address: 0xfc000
  end_address: 0x100000
  inside:
  - tfm_storage
  placement:
    align:
      start: 0x4000
    before:
    - end
  region: flash_primary
  size: 0x4000
tfm_secure:
  address: 0xc000
  end_address: 0x4c200
  orig_span: &id007
  - mcuboot_pad
  - tfm
  region: flash_primary
  size: 0x40200
  span: *id007
tfm_sram:
  address: 0x20002000
  end_address: 0x2000fd70
  inside:
  - sram_secure
  placement:
    after:
    - start
  region: sram_primary
  size: 0xdd70
tfm_storage:
  address: 0xf8000
  end_address: 0x100000
  orig_span: &id008
  - tfm_ps
  - tfm_its
  - tfm_otp_nv_counters
  region: flash_primary
  size: 0x8000
  span: *id008
Thanks,
  • That was a bummer, I will transfer the case to someone that can suggest how to do this using partion then.

    Kenneth

  • Hello,

    Yes, the UICR ranges you want to access from the app need to be added to the tfm-read ranges. Below is an example patch I made for the tfm_read_ranges.h header located in /v2.7.0/nrf/modules/trusted-firmware-m/tfm_boards/services/include:

    diff --git a/modules/trusted-firmware-m/tfm_boards/services/include/tfm_read_ranges.h b/modules/trusted-firmware-m/tfm_boards/services/include/tfm_read_ranges.h
    index a11c412a3..a393c1b73 100644
    --- a/modules/trusted-firmware-m/tfm_boards/services/include/tfm_read_ranges.h
    +++ b/modules/trusted-firmware-m/tfm_boards/services/include/tfm_read_ranges.h
    @@ -39,6 +39,11 @@
     #define FICR_RESTRICTED_ADDR (FICR_BASE + 0x130)
     #define FICR_RESTRICTED_SIZE 0x8
     
    +#ifdef NRF_UICR_S_BASE
    +#define UICR_CUSTOMER_DATA_ADDR     ((uint32_t) &NRF_UICR_S->OTP[0])
    +#define UICR_CUSTOMER_DATA_SIZE 	(sizeof(uint32_t))
    +#endif
    +
     #if defined(FICR_SIPINFO_PARTNO_PARTNO_Pos)
     #define FICR_SIPINFO_ADDR (FICR_BASE + offsetof(NRF_FICR_Type, SIPINFO))
     #define FICR_SIPINFO_SIZE (sizeof(FICR_SIPINFO_Type))
    @@ -74,6 +79,11 @@ static const struct tfm_read_service_range ranges[] = {
     #if defined(NRF_APPLICATION_CPUC_S)
     	{.start = CPUC_CPUID_ADDR, .size = CPUC_CPUID_SIZE},
     #endif
    +#if defined(UICR_CUSTOMER_DATA_ADDR)
    +	{ .start  = UICR_CUSTOMER_DATA_ADDR, .size = UICR_CUSTOMER_DATA_SIZE }, 
    +#endif 
     };
     
    +
    +
     #endif /* TFM_READ_RANGES_H__ */

    And here is the test code I used to verify that it worked:

    #include <soc_secure.h>
    
    int main(void)
    {
    	int err;
    	uint32_t read_buffer;
    
    	printf("Hello World! %s\n", CONFIG_BOARD_TARGET);
    
    	err = soc_secure_mem_read(&read_buffer, (void *)&NRF_UICR_S->OTP[0], sizeof(uint32_t));
    	if (err) {
    		printf("soc_secure_mem_read() failed. (err %d)\n", err);
    	} else {
    		printf("NRF_UICR_S->OTP[0] : 0x%x\n", read_buffer);
    	}
    
    	return 0;
    }
    

    Writing the OTP register with nrfjprog:

    $ nrfjprog --memwr 0xff8100  --val 0x12345

    Since the OTP region may be used to store secrets, TF-M does not expose this memory region by default. 

    Best regards,

    Vidar

  • Hi Vidar, 

    Thanks for your reply.

    Apologies I should have mentioned I'm using nRF connect sdk v2.2.0.The tfm_read_ranges.h file is in a different directory but seems to work the same with the changes applied.
    I found the file in "NRF_SDK\2.2.0\nrf\include\tfm\tfm_read_ranges.h"

    I think the function to read from the secure flash are different in this SDK version too, I used "secure_read_word" instead.

    Thanks,

  • Hi,

    I'm glad to hear that it worked, thanks for the update. The developers have made the following PRs to add support for reading the OTP registers in future SDK releases:

     - https://github.com/nrfconnect/sdk-nrf/pull/16927 

     - https://developer.nordicsemi.com/nRF_Connect_SDK_dev/doc/PR-16890/nrf/libraries/security/tfm/tfm_ioctl_api.html#read-service 

    Best regards,

    Vidar

Related