Hi,
Issue Description
We are testing S32K344 Secure Boot with NXP demo examples.
Using S32K344_SecureBootBlinky demo project, we generate the application .bin file.
Then, we use S32K344_Basic_SecureBoot demo project to run HSE_VerifyBootImage().
Observation
The first run of HSE_VerifyBootImage() succeeds: verification is OK.
However, when executing the same code a second time, the API returns:
HSE_SRV_RSP_GENERAL_ERROR
return code = 0x33d6d4f1
Questions
What is the root cause of this behavior?
Why does the first verify succeed, but the second verify fails with a general error?
Is there any restriction on calling HSE_VerifyBootImage() multiple times in a row?
Does NXP provide a complete Basic_SecureBoot demo code (not just HSE_VerifyBootImage()), but including boot from AppBL flow?
Environment
Demo code package: S32K3_HSE_DemoExamples_1_0_0
Target MCU: S32K344
Thanks for any help.
Best regards,
Mark
Hi @MarkFan
There are no restrictions, you can call HSE_VerifyBootImage several times. It works on my side.
The example S32K344_Basic_SecureBoot is complete example. BOOT_SEQ in boot configuration word is already set in this project, so secure boot is enabled right at the beginning:
When you load the project first time, the debugger sets the program counter "manually" at entry point (i.e. the boot header and BOOT_SEQ has no effect now). So, S32K344_Basic_SecureBoot project is executed. It performs the configuration of the secure boot. After next reset, S32K344_SecureBootBlinky will be executed if the secure boot is successful. If not, it will go to JTAG recovery mode. To execute S32K344_Basic_SecureBoot again, it would be necessary to change BOOT_SEQ to 1.
Another options is to keep BOOT_SEQ 0 and then change it manually in the flash once you want to turn the secure boot on.
Regards,
Lukas
Hi Lukas,
Thanks for your reply.
Do I need to program all 28 bytes (IV + GMAC) following the IVT?
My EVB (S32K344 BMU) does not have a reset pin. Is there a simple way to trigger an MCU reset?
Best regards,
Mark
Yes, all 28 bytes needs to be programmed to the flash.
The reset can be triggered by debugger or by software running on the device.
If you have Trace32, you can use attached script.
Hi Lukas,
Thanks for your help. I implemented the reset function and it works fine.
However, I noticed that in the S32K344_Basic_SecureBoot demo project, the IVT does not seem to program all 28 bytes (IV + GMAC). I tried to implement this function myself, but I received an HSE_SRV_RSP_INVALID_PARAM return code from HSE_SignBootImage().
Here is the code I used:
uint8_t temp_addr_of_ivt_image[28] = {0xFF};
(void)memcpy(
&IVT_temp,
(const void *)BLOCK0_BASE_ADDRESS,
IVT_FIXED_LENGTH
);
srvResponse = HSE_SignBootImage(
(uint8_t *)&IVT_temp,
BOOT_IMG_TAG_LEN,
temp_addr_of_ivt_image
);
Could you please help me check if there is something wrong with my code or the way I am using HSE_SignBootImage()?
Thanks,
Best regards,
Mark
Hi @MarkFan
Ok, so you are trying to sign IVT. Your code is correct, there's no problem. I also executed it on my board and it works. IV and GMAC was successfully generated by this code.
Isn't that data cache issue? Is IVT_temp in non-cacheable SRAM? And if you have stack in DTCM memory, do not use data on stack for HSE service. HSE can't see DTCM at normal addresses, HSE (and other bus masters) can see only backdoor addresses of DTCM.
For quick test, try to disable data cache completely.
Regards,
Lukas
Hi Lukas,
Thanks a lot for your help. Actually, I don’t know how to disable the data cache, but I moved IVT_temp to a global variable, and then the HSE_SignBootImage() function returned success.
However, I now have another issue: I cannot erase the flash address starting from 0x400000, which is where the IVT is located. I followed the sample erase and program sequence for AppBL, only changing the address, but I got an error when trying to erase the flash.
Here is the code snippet:
(void)memcpy(
&IVT_temp,
(const void *)BLOCK0_BASE_ADDRESS,
IVT_FIXED_LENGTH);
srvResponse = HSE_SignBootImage((uint8_t *)&IVT_temp, BOOT_IMG_TAG_LEN, temp_addr_of_ivt_image);
ASSERT(HSE_SRV_RSP_OK == srvResponse);
///* Write the generated TAG to the end of the IVT in FLASH */
PFLASH_Unlock(PFLASH_BL0, PFLASH_SS0, PFLASH_S0);
status = FLASH_EraseBlock(pIVT);
status = FLASH_Write(
pIVT,
&IVT_temp,
IVT_FIXED_LENGTH);
Do you have any suggestion or guidance on how to erase the IVT address (0x400000)?
Thanks in advance for your support.
Best regards,
Mark
1. What kind of error did you get?
2. Where the code is running from? Notice that read-while-write is supported only between blocks. If you are running flash operation on block 0, the code must be executed from another block or from RAM.
3. Do you really want to erase whole block? This command (status = FLASH_EraseBlock(pIVT);) will erase whole area 0x40_0000 - 0x4F_FFFF:
Regards,
Lukas
Hi Lukas,
Environment
Demo code package: S32K3_HSE_DemoExamples_1_0_0
example project : S32K344_Basic_SecureBoot
I tring to erase IVT address(0x400000) then program new IVT with 28byte (IV + GMAC).
In this project, I don't konw how to erase the address from 0x400000 to 0x4000100.
I used the code as below and check the memory. The Erase won't work.
PFLASH_Unlock(PFLASH_BL0, PFLASH_SS0, PFLASH_S0);
status = FLASH_EraseBlock(pIVT);
Exception error after FLASH_Write () function.
Could you provide with me some sample code can erase address(0x400000) can runing in this project, I realy need a sample code to prove OTA or secure boot an work in this S32K344 EVB.
Thanks for your support.
Best regards,
Mark
I'm sure that code like this works:
PFLASH_Unlock(PFLASH_BL0, PFLASH_SS0, PFLASH_S0);
status = FLASH_EraseSector(0x400000);
status = FLASH_Write (0x400000, data, sizeof(data));
However, as I wrote earlier, the code must run from another flash block or from RAM. An option how to move a function which triggers flash operation and which waits for completion of the command is to move it to data flash block, for example. You can create own section in dflash in linker file like this:
.dflash_code_section :
{
*(.dflash_code_section)
} > DFLASH
And then add this attribute before FLASH_ExecSeq() function in flash.c:
__attribute__((section(".dflash_code_section")))
tFLASH_STATUS FLASH_ExecSeq (register uint32_t mask)
This will force the function to data flash.
Then be aware that FLASH_EraseSector() will erase 8KB of flash. If there's your code (and it really is in default S32K344_Basic_SecureBoot example) then it will run away after return from FLASH_ExecSeq() because you erased your code. Solution: shift your code, so it starts at next 8KB sector. Keep only IVT in the first sector.
Regards,
Lukas