67 lines
1.9 KiB
C
67 lines
1.9 KiB
C
#include "main.h"
|
|
#include "flash.h"
|
|
#include "sha256.h"
|
|
#include "uECC.h"
|
|
|
|
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) {
|
|
if (!check_firmware(UPGRADE_FW_START)) {
|
|
upgrade_firmware();
|
|
} else if (check_firmware(FIRMWARE_START)) {
|
|
factory_reset();
|
|
}
|
|
|
|
run_firmware();
|
|
}
|
|
|
|
int check_firmware(uintptr_t addr) {
|
|
if(UINT32_PTR(addr)[0] != FW_MAGIC) {
|
|
return 1;
|
|
}
|
|
|
|
uint32_t fw_size = UINT32_PTR(addr)[1];
|
|
|
|
if (fw_size > FIRMWARE_SIZE) {
|
|
return 1;
|
|
}
|
|
|
|
uint8_t hash[CF_SHA256_HASHSZ];
|
|
cf_sha256_context ctx;
|
|
uECC_Curve ec_curve = uECC_secp256k1();
|
|
|
|
cf_sha256_init(&ctx);
|
|
cf_sha256_update(&ctx, UINT8_PTR(addr + FIRMWARE_HEADER_SIZE), fw_size);
|
|
cf_sha256_digest(&ctx, hash);
|
|
|
|
return uECC_verify(fw_public_key, hash, CF_SHA256_HASHSZ, UINT8_PTR(addr + 8), ec_curve) != 1;
|
|
}
|
|
|
|
|
|
void _load_firmware(uintptr_t newfw, uint8_t newfw_bank, uint8_t newfw_page) {
|
|
flash_unlock();
|
|
|
|
do {
|
|
flash_erase(FLASH_BANK1, FIRMWARE_FIRST_PAGE, FIRMWARE_PAGE_COUNT);
|
|
flash_copy(UINT32_PTR(newfw), UINT32_PTR(FIRMWARE_START), UINT32_PTR(newfw)[1]);
|
|
} while(check_firmware(FIRMWARE_START) != 0);
|
|
|
|
flash_erase(newfw_bank, newfw_page, FIRMWARE_PAGE_COUNT);
|
|
flash_lock();
|
|
}
|
|
|
|
void upgrade_firmware() {
|
|
_load_firmware(UPGRADE_FW_START, FLASH_BANK2, UPGRADE_FW_FIRST_PAGE);
|
|
}
|
|
|
|
void run_firmware(void) {
|
|
uint32_t* fw_entry = UINT32_PTR(FIRMWARE_CODE_START);
|
|
SCB->VTOR = (uint32_t) fw_entry;
|
|
__set_MSP(fw_entry[0]);
|
|
((void (*)(void))fw_entry[1])();
|
|
}
|
|
|
|
void factory_reset(void) {
|
|
_load_firmware(RECOVERY_FW_START, FLASH_BANK1, RECOVERY_FW_FIRST_PAGE);
|
|
}
|