wolfSSL / wolfBoot

wolfBoot is a portable, OS-agnostic, secure bootloader for microcontrollers, supporting firmware authentication and firmware update mechanisms.
https://www.wolfssl.com
GNU General Public License v3.0
331 stars 95 forks source link

Possible problem with power fail #406

Closed UffTechn closed 4 months ago

UffTechn commented 4 months ago

Good morning,

I am using WolfBoot 2.0.2 on STM32U585.

I am using dual swap capability and in normal condition all works like a charm.

My Flash partition is:

0x08000000 --> Wolfboot 0x08010000 --> Boot Image 0x08110000 --> Update image

The only (maybe) problem seems to occurs under this condition. 1) load a good image candidate at attress 0x08110000. 2) reboot the MCU

Then WolfBoot will execute

void RAMFUNCTION hal_flash_dualbank_swap(void)
{
    uint32_t cur_opts;
    hal_flash_unlock();
    hal_flash_opt_unlock();
    cur_opts = (FLASH_OPTR & FLASH_OPTR_SWAP_BANK) >> 20;
    if (cur_opts)
        FLASH_OPTR &= (~FLASH_OPTR_SWAP_BANK);
    else
        FLASH_OPTR |= FLASH_OPTR_SWAP_BANK;
    hal_flash_opt_lock();
    hal_flash_lock();
    stm32u5_reboot();
}

setting FLASH_OPTR_SWAP_BANK bit and reboot again the MCU. I notice that if a power failure occurs during the execution of fork_bootloader()

void hal_init(void)
{
#if defined(DUALBANK_SWAP) && defined(__WOLFBOOT)
    if ((FLASH_OPTR & (FLASH_OPTR_SWAP_BANK | FLASH_OPTR_DBANK)) == FLASH_OPTR_DBANK)
        fork_bootloader();

then the MCU is locked forever because FLASH_OPTR_SWAP_BANK was previously set to 1 and at location 0x08100000 there is wrong code or no code at all due to powerfailure.

My solution was to comment this line of code


//    if ((FLASH_OPTR & (FLASH_OPTR_SWAP_BANK | FLASH_OPTR_DBANK)) == FLASH_OPTR_DBANK)
//        fork_bootloader();

and to preload the WolfBoot binary at 0x08000000 --> Wolfboot 0x08100000 --> Wolfboot

In this way I solved the problem.

Am I missing something? Maybe I am doing something wrong.

Thank you

danielinux commented 4 months ago

Hey @UffTechn ,

Thanks for reporting this.

Your approach seems valid. The fork_bootloader() should do nothing if the contents already match. Which means it should only run once after the installation. Which would be equivalent (after the first run) to your current approach of flashing wolfBoot at the beginning of both banks.

I'm going to open a PR to address this the right way and update the porting documentation for the fork_bootloader() feature.

-- Daniele

danielinux commented 4 months ago

@UffTechn I changed the fork_bootloader call so that it returns immediately if the content in the second bank already matches. Please confirm this would solve your case, and regardless whether you want to upload the bootloader to both banks you should not need to comment out the invocation of the fork_bootloader() call.

Could you confirm this is a valid fix for your use case?

Thanks,

-- Daniele

UffTechn commented 4 months ago

@danielinux thanks for your prompt answer, we plan to test your modification today or Monday 19 at the latest. I will keep you updated.

UffTechn commented 4 months ago

@UffTechn I changed the fork_bootloader call so that it returns immediately if the content in the second bank already matches. Please confirm this would solve your case, and regardless whether you want to upload the bootloader to both banks you should not need to comment out the invocation of the fork_bootloader() call.

Could you confirm this is a valid fix for your use case?

Thanks,

-- Daniele

Hi @danielinux,

we test your fix and now it works as expected.

We can not reproduce the powerfail issue anymore.

Many thanks

Best regards

danielinux commented 4 months ago

Thanks for confirming! Closing this issue.