add code to protect the bootloader and the recovery firmware

This commit is contained in:
Michele Balistreri 2018-05-16 15:22:12 +03:00
parent 977242cf3d
commit 2287acead4
5 changed files with 67 additions and 4 deletions

View File

@ -94,9 +94,6 @@
</tool>
</toolChain>
</folderInfo>
<fileInfo id="fr.ac6.managedbuild.config.gnu.cross.exe.debug.671366655.1713612907" name="startup_stm32l476xx.s" rcbsApplicability="disable" resourcePath="startup/startup_stm32l476xx.s" toolsToInvoke="fr.ac6.managedbuild.tool.gnu.cross.assembler.1808416181.796708243">
<tool id="fr.ac6.managedbuild.tool.gnu.cross.assembler.1808416181.796708243" name="MCU GCC Assembler" superClass="fr.ac6.managedbuild.tool.gnu.cross.assembler.1808416181"/>
</fileInfo>
<sourceEntries>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="startup"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Drivers"/>
@ -145,6 +142,7 @@
</option>
<option id="gnu.c.compiler.option.preprocessor.def.symbols.2096171234" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols">
<listOptionValue builtIn="false" value="__weak=&quot;__attribute__((weak))&quot;"/>
<listOptionValue builtIn="false" value="-DBOOTLOADER_RELEASE"/>
<listOptionValue builtIn="false" value="__packed=&quot;__attribute__((__packed__))&quot;"/>
<listOptionValue builtIn="false" value="STM32L476xx"/>
</option>
@ -232,4 +230,5 @@
<configuration configurationName="Release"/>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
</cproject>

View File

@ -7,9 +7,19 @@
#define FLASH_KEYR1 0x45670123
#define FLASH_KEYR2 0xCDEF89AB
#define FLASH_OPTKEYR1 0x08192A3B
#define FLASH_OPTKEYR2 0x4C5D6E7F
#define FLASH_BANK1 0
#define FLASH_BANK2 1
#define RDP2 0xcc
#define FLASH_IS_RDP2() ((FLASH->OPTR & 0xff) == RDP2)
#define FLASH_SET_RDP2() FLASH->OPTR |= RDP2
#define FLASH_WP(reg, start, end) reg = (0xFF00FF00 | end << 16 | start)
/**
* Unlocks the flash, allowing writing.
*/
@ -31,4 +41,15 @@ int flash_copy(uint32_t* src, __IO uint32_t* dst, uint32_t size);
*/
int flash_lock();
/**
* Unlock the option bytes
*/
int flash_optunlock();
/**
* Write and reload the option bytes
*/
void flash_optprogram();
#endif /* FLASH_H_ */

View File

@ -8,9 +8,12 @@
// The constants below define the memory layout documented in the README.md file
#define BOOTLOADER_SIZE 0x2000
#define BOOTLOADER_FIRST_PAGE 0
#define BOOTLOADER_LAST_PAGE ((BOOTLOADER_SIZE / FLASH_PAGE_SIZE) - 1)
#define FIRMWARE_SIZE ((FLASH_BANK_SIZE - BOOTLOADER_SIZE) / 2)
#define FIRMWARE_HEADER_SIZE 0x200
#define FIRMWARE_FIRST_PAGE (BOOTLOADER_SIZE / FLASH_PAGE_SIZE)
#define FIRMWARE_FIRST_PAGE (BOOTLOADER_LAST_PAGE + 1)
#define FIRMWARE_PAGE_COUNT (FIRMWARE_SIZE / FLASH_PAGE_SIZE)
#define FIRMWARE_START (FLASH_START_BANK1 + BOOTLOADER_SIZE)
@ -21,6 +24,8 @@
#define RECOVERY_FW_START (FIRMWARE_START + FIRMWARE_SIZE)
#define RECOVERY_FW_FIRST_PAGE (FIRMWARE_FIRST_PAGE + FIRMWARE_PAGE_COUNT)
#define RECOVERY_FW_LAST_PAGE (RECOVERY_FW_FIRST_PAGE + FIRMWARE_PAGE_COUNT - 1)
#define SIGNATURE_HEADER_OFFSET 8
#define SIGNATURE_LENGTH 64
@ -28,6 +33,10 @@
#define SIGNATURE_COUNT 1
/**
* Checks if the bootloader and recovery are write protected, if not protect them. Also enables the Read Protection level 2. Since this is irreversible, the code is disabled during development
*/
void protect_flash();
/**
* Checks the firmware a the given address. It checks the magic number, validates the size and checks the signature(s).

View File

@ -18,6 +18,15 @@ int flash_unlock() {
return READ_BIT(FLASH->CR, FLASH_CR_LOCK);
}
int flash_optunlock() {
flash_unlock();
FLASH->OPTKEYR = FLASH_OPTKEYR1;
FLASH->OPTKEYR = FLASH_OPTKEYR2;
return READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK);
}
int _flash_erase_page(uint8_t bank, uint8_t pg) {
if(bank == FLASH_BANK1) {
CLEAR_BIT(FLASH->CR, FLASH_CR_BKER);
@ -77,3 +86,9 @@ int flash_lock() {
SET_BIT(FLASH->CR, FLASH_CR_LOCK);
return 0;
}
void flash_optprogram() {
SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
_flash_wait();
SET_BIT(FLASH->CR, FLASH_CR_OBL_LAUNCH);
}

View File

@ -6,6 +6,8 @@
uint8_t fw_public_key[] = { 0xfe, 0xcb, 0x28, 0xb9, 0x50, 0xdd, 0x8b, 0x2f, 0xc7, 0x34, 0xd3, 0x60, 0x5b, 0x1a, 0xc6, 0xed, 0x02, 0x50, 0xf2, 0x4a, 0xc4, 0x75, 0xd1, 0x28, 0x7f, 0x7c, 0xb5, 0xce, 0x61, 0xd6, 0x95, 0xb9, 0xb5, 0x27, 0x0b, 0x52, 0x77, 0x42, 0x4b, 0xf3, 0xb4, 0x3c, 0xef, 0xcb, 0x56, 0xd1, 0x98, 0x22, 0x11, 0xc2, 0xe5, 0xd3, 0xf0, 0x22, 0x87, 0xb9, 0xe8, 0x20, 0xdc, 0xee, 0x9f, 0xc2, 0xad, 0x22, };
int main(void) {
protect_flash();
if (!check_firmware(UPGRADE_FW_START)) {
upgrade_firmware();
} else if (check_firmware(FIRMWARE_START)) {
@ -43,6 +45,23 @@ int check_firmware(uintptr_t addr) {
return 0;
}
void protect_flash() {
#ifdef BOOTLOADER_RELEASE
if (FLASH_IS_RDP2()) {
return;
}
flash_optunlock();
FLASH_SET_RDP2();
FLASH_WP(FLASH->WRP1AR, BOOTLOADER_FIRST_PAGE, BOOTLOADER_LAST_PAGE);
FLASH_WP(FLASH->WRP1BR, RECOVERY_FW_FIRST_PAGE, RECOVERY_FW_LAST_PAGE);
// This resets the MCU
flash_optprogram();
#endif
}
void _load_firmware(uintptr_t newfw, uint8_t newfw_bank, uint8_t newfw_page, uint8_t remove_newfw) {
flash_unlock();