mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-22 15:38:11 +00:00
bootloader: allow stage 1 to rewrite whole flash
This commit is contained in:
parent
d8efa32091
commit
89ec08eec0
@ -6,15 +6,24 @@
|
||||
#include "display.h"
|
||||
#include "sdcard.h"
|
||||
|
||||
#define STAGE2_SECTOR 4
|
||||
#define STAGE2_START 0x08010000
|
||||
#define STAGE2_SIZE (64 * 1024)
|
||||
|
||||
#define BOOTLOADER_PRINT(X) display_print(X, -1)
|
||||
#define BOOTLOADER_PRINTLN(X) display_print(X "\n", -1)
|
||||
|
||||
void SystemClock_Config(void);
|
||||
|
||||
void halt(void)
|
||||
{
|
||||
BOOTLOADER_PRINTLN("HALT!");
|
||||
for (;;) {
|
||||
display_backlight(255);
|
||||
HAL_Delay(950);
|
||||
display_backlight(0);
|
||||
HAL_Delay(50);
|
||||
}
|
||||
}
|
||||
|
||||
void periph_init(void)
|
||||
{
|
||||
HAL_Init();
|
||||
@ -47,7 +56,7 @@ bool check_sdcard(void)
|
||||
sdcard_power_on();
|
||||
|
||||
uint64_t cap = sdcard_get_capacity_in_bytes();
|
||||
if (cap < STAGE2_SIZE) {
|
||||
if (cap < 1024 * 1024) {
|
||||
BOOTLOADER_PRINTLN("SD card too small");
|
||||
sdcard_power_off();
|
||||
return false;
|
||||
@ -59,7 +68,8 @@ bool check_sdcard(void)
|
||||
|
||||
sdcard_power_off();
|
||||
|
||||
if (check_header(buf)) {
|
||||
uint32_t codelen;
|
||||
if (parse_header(buf, &codelen)) {
|
||||
BOOTLOADER_PRINTLN("SD card header is valid");
|
||||
return true;
|
||||
} else {
|
||||
@ -68,55 +78,63 @@ bool check_sdcard(void)
|
||||
}
|
||||
}
|
||||
|
||||
void copy_sdcard(void)
|
||||
bool copy_sdcard(void)
|
||||
{
|
||||
|
||||
BOOTLOADER_PRINTLN("erasing old stage 2");
|
||||
BOOTLOADER_PRINT("erasing flash ");
|
||||
|
||||
// erase STAGE2_SECTOR
|
||||
// erase flash (except stage 1)
|
||||
HAL_FLASH_Unlock();
|
||||
FLASH_EraseInitTypeDef EraseInitStruct;
|
||||
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |
|
||||
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
|
||||
EraseInitStruct.TypeErase = TYPEERASE_SECTORS;
|
||||
EraseInitStruct.VoltageRange = VOLTAGE_RANGE_3; // voltage range needs to be 2.7V to 3.6V
|
||||
EraseInitStruct.Sector = STAGE2_SECTOR;
|
||||
EraseInitStruct.NbSectors = 1;
|
||||
uint32_t SectorError = 0;
|
||||
if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) {
|
||||
HAL_FLASH_Lock();
|
||||
return;
|
||||
for (int i = 3; i <= 11; i++) { // TODO: change start to 2
|
||||
EraseInitStruct.Sector = i;
|
||||
if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) {
|
||||
HAL_FLASH_Lock();
|
||||
BOOTLOADER_PRINTLN(" failed");
|
||||
return false;
|
||||
}
|
||||
BOOTLOADER_PRINT(".");
|
||||
}
|
||||
BOOTLOADER_PRINTLN(" done");
|
||||
|
||||
BOOTLOADER_PRINTLN("copying new stage 2 from SD card");
|
||||
|
||||
sdcard_power_on();
|
||||
|
||||
// copy stage 2 from SD card to Flash
|
||||
uint32_t buf[SDCARD_BLOCK_SIZE / sizeof(uint32_t)];
|
||||
sdcard_read_blocks((uint8_t *)buf, 0, 1);
|
||||
|
||||
sdcard_power_on();
|
||||
for (int i = 0; i < STAGE2_SIZE / SDCARD_BLOCK_SIZE; i++) {
|
||||
uint32_t codelen;
|
||||
if (!parse_header((uint8_t *)buf, &codelen)) {
|
||||
BOOTLOADER_PRINTLN("wrong header");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < codelen / SDCARD_BLOCK_SIZE; i++) {
|
||||
sdcard_read_blocks((uint8_t *)buf, i, 1);
|
||||
for (int j = 0; j < SDCARD_BLOCK_SIZE / sizeof(uint32_t); j++) {
|
||||
if (HAL_FLASH_Program(TYPEPROGRAM_WORD, STAGE2_START + i * SDCARD_BLOCK_SIZE + j * sizeof(uint32_t), buf[j]) != HAL_OK) {
|
||||
break;
|
||||
BOOTLOADER_PRINTLN("copy failed");
|
||||
sdcard_power_off();
|
||||
HAL_FLASH_Lock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
sdcard_power_off();
|
||||
|
||||
sdcard_power_off();
|
||||
HAL_FLASH_Lock();
|
||||
|
||||
BOOTLOADER_PRINTLN("done");
|
||||
}
|
||||
|
||||
void halt(void)
|
||||
{
|
||||
for (;;) {
|
||||
display_backlight(255);
|
||||
HAL_Delay(950);
|
||||
display_backlight(0);
|
||||
HAL_Delay(50);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
@ -129,11 +147,14 @@ int main(void)
|
||||
BOOTLOADER_PRINTLN("starting stage 1");
|
||||
|
||||
if (check_sdcard()) {
|
||||
copy_sdcard();
|
||||
if (!copy_sdcard()) {
|
||||
halt();
|
||||
}
|
||||
}
|
||||
|
||||
BOOTLOADER_PRINTLN("checking stage 2");
|
||||
if (check_header((const uint8_t *)STAGE2_START)) {
|
||||
uint32_t codelen;
|
||||
if (parse_header((const uint8_t *)STAGE2_START, &codelen)) {
|
||||
BOOTLOADER_PRINTLN("valid stage 2 header");
|
||||
if (check_signature()) {
|
||||
BOOTLOADER_PRINTLN("valid stage 2 signature");
|
||||
@ -147,7 +168,6 @@ int main(void)
|
||||
BOOTLOADER_PRINTLN("invalid stage 2 header");
|
||||
}
|
||||
|
||||
BOOTLOADER_PRINTLN("HALT!");
|
||||
halt();
|
||||
|
||||
return 0;
|
||||
|
@ -17,7 +17,7 @@ bool ed25519_verify(const uint8_t *msg, uint32_t msglen, const uint8_t *pubkey,
|
||||
return (0 == ed25519_sign_open(msg, msglen, *(const ed25519_public_key *)pubkey, *(const ed25519_signature *)signature));
|
||||
}
|
||||
|
||||
bool check_header(const uint8_t *data)
|
||||
bool parse_header(const uint8_t *data, uint32_t *codelen)
|
||||
{
|
||||
uint32_t magic;
|
||||
memcpy(&magic, data, 4);
|
||||
@ -31,9 +31,11 @@ bool check_header(const uint8_t *data)
|
||||
memcpy(&expiry, data + 8, 4);
|
||||
if (expiry != 0) return false;
|
||||
|
||||
uint32_t codelen;
|
||||
memcpy(&codelen, data + 12, 4);
|
||||
if (codelen != 64 * 1024 - 256) return false;
|
||||
memcpy(codelen, data + 12, 4);
|
||||
// stage 2 (+header) must fit into sectors 4...11 - see docs/memory.md for more info
|
||||
if (*codelen + hdrlen < 4 * 1024) return false;
|
||||
if (*codelen + hdrlen > 64 * 1024 + 7 * 128 * 1024) return false;
|
||||
if ((*codelen + hdrlen) % 512 != 0) return false;
|
||||
|
||||
uint32_t version;
|
||||
memcpy(&version, data + 16, 4);
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
bool check_header(const uint8_t *data);
|
||||
bool parse_header(const uint8_t *data, uint32_t *codelen);
|
||||
|
||||
bool check_signature(void);
|
||||
|
||||
|
BIN
tools/bootloader.bin
Normal file
BIN
tools/bootloader.bin
Normal file
Binary file not shown.
@ -42,10 +42,12 @@ class BootloaderImage:
|
||||
self.reserved, self.sigidx, self.sig = header
|
||||
assert self.magic == b'TRZB'
|
||||
assert self.hdrlen == 256
|
||||
assert self.codelen == 64*1024 - 256
|
||||
assert self.codelen + self.hdrlen >= 4 * 1024
|
||||
assert self.codelen + self.hdrlen <= 64 * 1024 + 7 * 128 * 1024
|
||||
assert (self.codelen + self.hdrlen) % 512 == 0
|
||||
assert self.reserved == 171 * b'\x00'
|
||||
self.sigidx = bitmap_to_tuple(self.sigidx)
|
||||
self.code = data[256:]
|
||||
self.code = data[self.hdrlen:]
|
||||
assert len(self.code) == self.codelen
|
||||
|
||||
def print(self):
|
||||
@ -68,11 +70,13 @@ class BootloaderImage:
|
||||
header += struct.pack('<B64s', sigidx, self.sig)
|
||||
else:
|
||||
header += 65 * b'\x00'
|
||||
assert len(header) == self.hdrlen
|
||||
return header
|
||||
|
||||
def sign(self):
|
||||
header = self.header(sig=False)
|
||||
data = header + self.code
|
||||
assert len(data) == self.hdrlen + self.codelen
|
||||
self.sigidx, self.sig = get_sig(data)
|
||||
|
||||
def write(self, filename):
|
||||
@ -141,6 +145,7 @@ class VendorHeader:
|
||||
header += struct.pack('<B64s', sigidx, self.sig)
|
||||
else:
|
||||
header += 65 * b'\x00'
|
||||
assert len(header) == self.hdrlen
|
||||
return header
|
||||
|
||||
def sign(self):
|
||||
@ -164,7 +169,7 @@ class FirmwareImage:
|
||||
assert self.codelen % 4 == 0
|
||||
assert self.reserved == 171 * b'\x00'
|
||||
self.sigidx = bitmap_to_tuple(self.sigidx)
|
||||
self.code = data[256:]
|
||||
self.code = data[self.hdrlen:]
|
||||
assert len(self.code) == self.codelen
|
||||
|
||||
def print(self):
|
||||
@ -187,11 +192,13 @@ class FirmwareImage:
|
||||
header += struct.pack('<B64s', sigidx, self.sig)
|
||||
else:
|
||||
header += 65 * b'\x00'
|
||||
assert len(header) == self.hdrlen
|
||||
return header
|
||||
|
||||
def sign(self):
|
||||
header = self.header(sig=False)
|
||||
data = header + self.code
|
||||
assert len(data) == self.hdrlen + self.codelen
|
||||
self.sigidx, self.sig = get_sig(data)
|
||||
|
||||
def write(self, filename):
|
||||
|
Loading…
Reference in New Issue
Block a user