cancel
Showing results for 
Search instead for 
Did you mean: 

memory map adjust SBSFU on a STM32G474

dominik
Senior

Hi

I'm using the dual image function on a 512kB STM32G474. I like to adjust the bootloader size to 32kb because my user App is too big.

In the AN5056 there is a note how to adjust it, but I'm not sure if this lines in the file low_level_security.h are correct? Can anybody help me please?

#define SFU_PROTECT_MPU_EXEC_SE_RGNV  MPU_REGION_NUMBER7
#define SFU_PROTECT_MPU_EXEC_SE_START FLASH_BASE           /*!< Flash memory area */
#define SFU_PROTECT_MPU_EXEC_SE_SIZE  MPU_REGION_SIZE_16KB //eud MPU_REGION_SIZE_32KB
#if defined (__GNUC__)
#define SFU_PROTECT_MPU_EXEC_SE_SREG  0xE0U                /*!< 32 Kbytes / 8 * 5 ==> 20 Kbytes */
#elif defined(__CC_ARM)
#define SFU_PROTECT_MPU_EXEC_SE_SREG  0x80U                /*!< 32 Kbytes / 8 * 7 ==> 28 Kbytes */
#else
#define SFU_PROTECT_MPU_EXEC_SE_SREG  0xC0U                /*!< 32 Kbytes / 8 * 6 ==> 24 Kbytes */
#endif /* (__GNUC__) */
#define SFU_PROTECT_MPU_EXEC_SE_PERM  MPU_REGION_PRIV_RO
#define SFU_PROTECT_MPU_EXEC_SE_EXECV MPU_INSTRUCTION_ACCESS_ENABLE
#define SFU_PROTECT_MPU_EXEC_SE_TEXV  MPU_TEX_LEVEL0
#define SFU_PROTECT_MPU_EXEC_SE_B     MPU_ACCESS_NOT_BUFFERABLE
#define SFU_PROTECT_MPU_EXEC_SE_C     MPU_ACCESS_CACHEABLE

Is the setting for SFU_PROTECT_MPU_EXEC_SE_SREG the same like before?

thanks

/*###ICF### Set of symbols used in SE and SB_SFU projects ****/
 
/* Slots Regions must be aligned on 4096 bytes (0x1000) */
 
/* swap region (8 Kbytes) */
define exported symbol  __ICFEDIT_region_SWAP_start__  = 0x08042000;
define exported symbol  __ICFEDIT_region_SWAP_end__    = 0x08043FFF;
 
/* slot 0 region (232 Kbytes) */
define exported symbol  __ICFEDIT_region_SLOT_0_start__= 0x08008000;
define exported symbol  __ICFEDIT_region_SLOT_0_end__  = 0x08041FFF;
 
/* slot 1 region (232 KBytes) */
define exported symbol  __ICFEDIT_region_SLOT_1_start__= 0x08044000;
define exported symbol  __ICFEDIT_region_SLOT_1_end__  = 0x0807DFFF;
 
/* firmware images regions definition */
define region SWAP_region   = mem:[from __ICFEDIT_region_SWAP_start__ to __ICFEDIT_region_SWAP_end__];
define region SLOT_0_region = mem:[from __ICFEDIT_region_SLOT_0_start__ to __ICFEDIT_region_SLOT_0_end__];
define region SLOT_1_region = mem:[from __ICFEDIT_region_SLOT_1_start__ to __ICFEDIT_region_SLOT_1_end__];
/* SE Startup: call before enabling protected area */
define exported symbol __ICFEDIT_SE_Startup_region_ROM_start__    = __ICFEDIT_SE_Key_region_ROM_end__ + 1;
define exported symbol __ICFEDIT_SE_Code_nokey_region_ROM_start__ = __ICFEDIT_SE_Startup_region_ROM_start__ + 0x100;
/* Aligned SE End at the end of the 1st 12Kbytes of flash, MPU protection isolation constraints */
define exported symbol __ICFEDIT_SE_Code_region_ROM_end__         = 0x08002FFF;
 
/* SE IF ROM: used to locate Secure Engine interface code out of protected area */
define exported symbol __ICFEDIT_SE_IF_region_ROM_start__         = __ICFEDIT_SE_Code_region_ROM_end__ + 1;
define exported symbol __ICFEDIT_SE_IF_region_ROM_end__           = __ICFEDIT_SE_IF_region_ROM_start__ + 0x5FF;
 
/* SBSFU Code region */
define exported symbol __ICFEDIT_SB_region_ROM_start__            = __ICFEDIT_SE_IF_region_ROM_end__ + 1;
/* Aligned SBSFU end at the end of the 1st 32Kbytes of FLASH, MPU protection isolation constraints */
define exported symbol __ICFEDIT_SB_region_ROM_end__              = 0x08007FFF;

1 ACCEPTED SOLUTION

Accepted Solutions
dominik
Senior

@Tilen MAJERLE​ , @Jocelyn RICARD​ 

The problem is solved, thaks a lot for your answers.

The bug was that I made a mistake when receiving the UART data with DMA and got an Array overflow which resulted in a HardFault.

The code to handle the ringbuffer is now like this

void CheckUsart1RXMessage (void)
{
    size_t len;
    uint8_t *data;
 
    if ((len = ringbuff_get_linear_block_read_length(&usart1_rx_dma_ringbuff)) > 0)
    {
        data = ringbuff_get_linear_block_read_address(&usart1_rx_dma_ringbuff);
        //check the message
        rx_message_f(data, len);
        /* Now skip sent bytes from buffer = move read pointer */
        ringbuff_skip(&usart1_rx_dma_ringbuff, len);
    }
}
 

the RAM is defined with 0x1FFFF (128kb) and I calculated with 0x1FFF (8kb). So this is not a problem anymore, I use now 0x4000 Stack size (16kb) and 0x1000 (4kb) Heap size. This is more than enough.

Thanks and best Regards, Dominik

View solution in original post

20 REPLIES 20
Jocelyn RICARD
ST Employee

Hello Dominik,

you didn't describe what you did to reduce bootloader size.

From your description you manage to reduce secure engine size from 24Kbytes to 12Kbytes ( 0x3000)

Regarding MPU configuration, you reduced the region size from 32KB to 16 kB.

So, each sub region is now 2KB instead of 4KB.

So, you need to set the 6 first subregions (2KB *6 = 12 KB) out if 8.

This means SFU_PROTECT_MPU_EXEC_SE_SREG should be 0xC0 and not 0xE0.

Best regards

Jocelyn

dominik
Senior

Hello Jocelyn

I disabled the Debug Outputs and now my bootloader size from the project 2_Images_SECoreBin has 17638 bytes. Defined in the icf file "mapping_sbsfu.icf" for this part is 24kB:

/* Aligned SE End at the end of the 1st 24Kbytes of flash, MPU protection isolation constraints */
define exported symbol __ICFEDIT_SE_Code_region_ROM_end__         = 0x08005FFF;

The project 2_Images_SBSFU has a size of 20910 bytes (20'910 bytes of readonly code memory)

In the icf file the region is defined with 64kB:

/* SBSFU Code region */
define exported symbol __ICFEDIT_SB_region_ROM_start__            = __ICFEDIT_SE_IF_region_ROM_end__ + 1;
/* Aligned SBSFU end at the end of the 1st 64Kbytes of FLASH, MPU protection isolation constraints */
define exported symbol __ICFEDIT_SB_region_ROM_end__              = 0x0800FFFF;

Together I need 17638 bytes + 20910 bytes = 38548 bytes.

Therefore its not possible, to place the code inside of the first 32kB, but it would be possible to place it in the first 48kB instead of 64kb.

In the file sfu_low_level_security.h the setting with 48kB is not possible like I can see:

#define   MPU_REGION_SIZE_16KB       ((uint8_t)0x0D)
#define   MPU_REGION_SIZE_32KB       ((uint8_t)0x0E)
#define   MPU_REGION_SIZE_64KB       ((uint8_t)0x0F)

If I am able to reduce the code to fit in 32kB, I can use the 32kB setting I guess.

You wrote:

Regarding MPU configuration, you reduced the region size from 32KB to 16 kB.

So, each sub region is now 2KB instead of 4KB.

So, you need to set the 6 first subregions (2KB *6 = 12 KB) out if 8.

This means SFU_PROTECT_MPU_EXEC_SE_SREG should be 0xC0 and not 0xE0.

Why the sub-region is now 2kB and not 4kB?

So, you need to set the 6 first subregions (2KB *6 = 12 KB) out if 8.

I'm using the IAR compiler, how is the value 0xE0 calculated?

dominik
Senior

I disabled the SECBOOT_USE_LOCAL_LOADER but its still not enough to fit inside of the 32kB, what I can try is to use the AES-GCM, maybe this helps to fit in the 32kB.

Otherwise I have to change to a 1Image solution, but this is not really what I like to do. Maybe some 1MB chips of the STM32G474 are in the pipeline?

dominik
Senior

@Jocelyn RICARD​ 

I managed to change to SECBOOT_AES128_GCM_AES128_GCM_AES128_GCM mode and now the Bootloader fits inside the 32kB.

But I still have no idea how the value for SFU_PROTECT_MPU_EXEC_SE_SREG is getting calculated, can you please help me with this part?

#define SFU_PROTECT_MPU_EXEC_SE_RGNV  MPU_REGION_NUMBER7
#define SFU_PROTECT_MPU_EXEC_SE_START FLASH_BASE           /*!< Flash memory area */
#define SFU_PROTECT_MPU_EXEC_SE_SIZE  MPU_REGION_SIZE_16KB //eud MPU_REGION_SIZE_32KB
#if defined (__GNUC__)
#define SFU_PROTECT_MPU_EXEC_SE_SREG  0xE0U                /*!< 32 Kbytes / 8 * 5 ==> 20 Kbytes */
#elif defined(__CC_ARM)
#define SFU_PROTECT_MPU_EXEC_SE_SREG  0x80U                /*!< 32 Kbytes / 8 * 7 ==> 28 Kbytes */
#else
#define SFU_PROTECT_MPU_EXEC_SE_SREG  0xC0U                /*!< 32 Kbytes / 8 * 6 ==> 24 Kbytes */
#endif /* (__GNUC__) */

Jocelyn RICARD
ST Employee

Hi Dominik,

You have reduced the region size from 32KB to 16 KB.

The MPU is able to manage 8 sub regions in this region. This is why you have now 8*2KB subregions.

The subregions are used to improve the granularity of the MPU.

The SREG (Subregion register) is a 8bit bitmap.

If bit value = 0 the subregion takes the configuration of the regions

If bit value = 1 the subregion is not concerned.

So, if you want that the first 12KB are protected by this region, you need to set the value 0xC0 to the bit map of SREG.

Bit 0 is for first 2KB, bit 1 for the next and so on.

I hope this answers your question.

Best regards

Jocelyn

Hi Jocelyn

Its working now with 0xC0. and 6 x 2kB = 12kB is because of the setting in the icf file, correct?

/* Aligned SE End at the end of the 1st 12Kbytes of flash, MPU protection isolation constraints */
define exported symbol __ICFEDIT_SE_Code_region_ROM_end__         = 0x08002FFF;

Just wondering on which line I have to implement with the IAR compiler on the STM32G474 -> defined(__CC_ARM)? Why is this setting different according to the compiler?

Startup Time is now longer with the SECBOOT_AES128_GCM_AES128_GCM_AES128_GCM but this is ok.

In the UM2262 there is the line on page 71: For the symmetric cryptographic scheme, it is highly recommended to configure a unique symmetric key for each product. What is the meaning of each product? Does this mean that I have to build a new application for every board? The bootloader and key is always the same, otherwise my application is not compatible for all boards in the market and this is not the goal of course.

Is there an additional information about the difference to the AES128-CBC? I saw that GCM is safe as long as I generate a new key for each product, but of course I like to build a new application for all boards in the market. Can you explain what is the meaning of "configure a unique symmetric key for each product".

Thanks a lot

dominik
Senior

@Jocelyn RICARD​ 

Can you please get back to my question above?

Its working now with 0xC0. and 6 x 2kB = 12kB is because of the setting in the icf file, correct?

And if I generate a new GCM key, the applications are not compatible anymore with the dfferent keys. So How should I generate a new key for each product and stay compatible with all boards in the field? I like to update all n boards in the field with the same application if there are some changes in the future.

-> "configure a unique symmetric key for each product"

Thanks a lot for your time, Regards

Jocelyn RICARD
ST Employee

Hi Dominik,

Setting is different in original code because of the size of compiled code is different with each compiler.

Well you allocated 12KB for the Secure Engine in the icf file reason why the MPU has to be aligned to this.

Startup time must be shorter using symmetric cryptography. There must be something wrong somewhere.

About the symmetric key, I think the sentence in the UM2262 is a bit misleading. A product here is not a unique device. This warning is raised here to tell you that you should not use the same key in all your different products (with different hw and/or SW).

Reason for this is that is symmetric key leaks, hacker can forge a firmware that will he authentic.

So, this crypto scheme is less secure compared to asymmetric cryptography.

One thing you need to consider is that GCM uses a nonce. This nonce must be used only once as name suggests. This nonce is provided in the header of the firmware. This is really important for GCM that you never have 2 different firmwares encrypted using same nonce in the field.

I hope this answers your question

Best regards

Jocelyn

0693W000007CsHcQAK.jpgHi @Jocelyn RICARD​ 

Thanks for your answer, yes, all clear now thanks. You are talking about this node like in the picture, right?

Like I understand, I need change this node everytime when I generate a new GCM key for a Bootloader/Application, right?

The Startup-Time is shorter yes, about 2.9s now, before was 4.038s, but without log it seems to be longer

Thanks a lot, Regards, Dominik