1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-26 17:38:39 +00:00

bootloader: allow stage 1 to rewrite whole flash

This commit is contained in:
Pavol Rusnak 2017-02-17 17:11:34 +01:00
parent d8efa32091
commit 89ec08eec0
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D
5 changed files with 64 additions and 35 deletions

View File

@ -6,15 +6,24 @@
#include "display.h" #include "display.h"
#include "sdcard.h" #include "sdcard.h"
#define STAGE2_SECTOR 4
#define STAGE2_START 0x08010000 #define STAGE2_START 0x08010000
#define STAGE2_SIZE (64 * 1024)
#define BOOTLOADER_PRINT(X) display_print(X, -1) #define BOOTLOADER_PRINT(X) display_print(X, -1)
#define BOOTLOADER_PRINTLN(X) display_print(X "\n", -1) #define BOOTLOADER_PRINTLN(X) display_print(X "\n", -1)
void SystemClock_Config(void); 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) void periph_init(void)
{ {
HAL_Init(); HAL_Init();
@ -47,7 +56,7 @@ bool check_sdcard(void)
sdcard_power_on(); sdcard_power_on();
uint64_t cap = sdcard_get_capacity_in_bytes(); uint64_t cap = sdcard_get_capacity_in_bytes();
if (cap < STAGE2_SIZE) { if (cap < 1024 * 1024) {
BOOTLOADER_PRINTLN("SD card too small"); BOOTLOADER_PRINTLN("SD card too small");
sdcard_power_off(); sdcard_power_off();
return false; return false;
@ -59,7 +68,8 @@ bool check_sdcard(void)
sdcard_power_off(); sdcard_power_off();
if (check_header(buf)) { uint32_t codelen;
if (parse_header(buf, &codelen)) {
BOOTLOADER_PRINTLN("SD card header is valid"); BOOTLOADER_PRINTLN("SD card header is valid");
return true; return true;
} else { } 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(); HAL_FLASH_Unlock();
FLASH_EraseInitTypeDef EraseInitStruct; FLASH_EraseInitTypeDef EraseInitStruct;
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
EraseInitStruct.TypeErase = TYPEERASE_SECTORS; EraseInitStruct.TypeErase = TYPEERASE_SECTORS;
EraseInitStruct.VoltageRange = VOLTAGE_RANGE_3; // voltage range needs to be 2.7V to 3.6V EraseInitStruct.VoltageRange = VOLTAGE_RANGE_3; // voltage range needs to be 2.7V to 3.6V
EraseInitStruct.Sector = STAGE2_SECTOR;
EraseInitStruct.NbSectors = 1; EraseInitStruct.NbSectors = 1;
uint32_t SectorError = 0; uint32_t SectorError = 0;
if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) { for (int i = 3; i <= 11; i++) { // TODO: change start to 2
HAL_FLASH_Lock(); EraseInitStruct.Sector = i;
return; 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"); BOOTLOADER_PRINTLN("copying new stage 2 from SD card");
sdcard_power_on();
// copy stage 2 from SD card to Flash // copy stage 2 from SD card to Flash
uint32_t buf[SDCARD_BLOCK_SIZE / sizeof(uint32_t)]; uint32_t buf[SDCARD_BLOCK_SIZE / sizeof(uint32_t)];
sdcard_read_blocks((uint8_t *)buf, 0, 1);
sdcard_power_on(); uint32_t codelen;
for (int i = 0; i < STAGE2_SIZE / SDCARD_BLOCK_SIZE; i++) { 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); sdcard_read_blocks((uint8_t *)buf, i, 1);
for (int j = 0; j < SDCARD_BLOCK_SIZE / sizeof(uint32_t); j++) { 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) { 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(); HAL_FLASH_Lock();
BOOTLOADER_PRINTLN("done"); BOOTLOADER_PRINTLN("done");
}
void halt(void) return true;
{
for (;;) {
display_backlight(255);
HAL_Delay(950);
display_backlight(0);
HAL_Delay(50);
}
} }
int main(void) int main(void)
@ -129,11 +147,14 @@ int main(void)
BOOTLOADER_PRINTLN("starting stage 1"); BOOTLOADER_PRINTLN("starting stage 1");
if (check_sdcard()) { if (check_sdcard()) {
copy_sdcard(); if (!copy_sdcard()) {
halt();
}
} }
BOOTLOADER_PRINTLN("checking stage 2"); 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"); BOOTLOADER_PRINTLN("valid stage 2 header");
if (check_signature()) { if (check_signature()) {
BOOTLOADER_PRINTLN("valid stage 2 signature"); BOOTLOADER_PRINTLN("valid stage 2 signature");
@ -147,7 +168,6 @@ int main(void)
BOOTLOADER_PRINTLN("invalid stage 2 header"); BOOTLOADER_PRINTLN("invalid stage 2 header");
} }
BOOTLOADER_PRINTLN("HALT!");
halt(); halt();
return 0; return 0;

View File

@ -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)); 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; uint32_t magic;
memcpy(&magic, data, 4); memcpy(&magic, data, 4);
@ -31,9 +31,11 @@ bool check_header(const uint8_t *data)
memcpy(&expiry, data + 8, 4); memcpy(&expiry, data + 8, 4);
if (expiry != 0) return false; if (expiry != 0) return false;
uint32_t codelen; memcpy(codelen, data + 12, 4);
memcpy(&codelen, data + 12, 4); // stage 2 (+header) must fit into sectors 4...11 - see docs/memory.md for more info
if (codelen != 64 * 1024 - 256) return false; 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; uint32_t version;
memcpy(&version, data + 16, 4); memcpy(&version, data + 16, 4);

View File

@ -4,7 +4,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.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); bool check_signature(void);

BIN
tools/bootloader.bin Normal file

Binary file not shown.

View File

@ -42,10 +42,12 @@ class BootloaderImage:
self.reserved, self.sigidx, self.sig = header self.reserved, self.sigidx, self.sig = header
assert self.magic == b'TRZB' assert self.magic == b'TRZB'
assert self.hdrlen == 256 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' assert self.reserved == 171 * b'\x00'
self.sigidx = bitmap_to_tuple(self.sigidx) self.sigidx = bitmap_to_tuple(self.sigidx)
self.code = data[256:] self.code = data[self.hdrlen:]
assert len(self.code) == self.codelen assert len(self.code) == self.codelen
def print(self): def print(self):
@ -68,11 +70,13 @@ class BootloaderImage:
header += struct.pack('<B64s', sigidx, self.sig) header += struct.pack('<B64s', sigidx, self.sig)
else: else:
header += 65 * b'\x00' header += 65 * b'\x00'
assert len(header) == self.hdrlen
return header return header
def sign(self): def sign(self):
header = self.header(sig=False) header = self.header(sig=False)
data = header + self.code data = header + self.code
assert len(data) == self.hdrlen + self.codelen
self.sigidx, self.sig = get_sig(data) self.sigidx, self.sig = get_sig(data)
def write(self, filename): def write(self, filename):
@ -141,6 +145,7 @@ class VendorHeader:
header += struct.pack('<B64s', sigidx, self.sig) header += struct.pack('<B64s', sigidx, self.sig)
else: else:
header += 65 * b'\x00' header += 65 * b'\x00'
assert len(header) == self.hdrlen
return header return header
def sign(self): def sign(self):
@ -164,7 +169,7 @@ class FirmwareImage:
assert self.codelen % 4 == 0 assert self.codelen % 4 == 0
assert self.reserved == 171 * b'\x00' assert self.reserved == 171 * b'\x00'
self.sigidx = bitmap_to_tuple(self.sigidx) self.sigidx = bitmap_to_tuple(self.sigidx)
self.code = data[256:] self.code = data[self.hdrlen:]
assert len(self.code) == self.codelen assert len(self.code) == self.codelen
def print(self): def print(self):
@ -187,11 +192,13 @@ class FirmwareImage:
header += struct.pack('<B64s', sigidx, self.sig) header += struct.pack('<B64s', sigidx, self.sig)
else: else:
header += 65 * b'\x00' header += 65 * b'\x00'
assert len(header) == self.hdrlen
return header return header
def sign(self): def sign(self):
header = self.header(sig=False) header = self.header(sig=False)
data = header + self.code data = header + self.code
assert len(data) == self.hdrlen + self.codelen
self.sigidx, self.sig = get_sig(data) self.sigidx, self.sig = get_sig(data)
def write(self, filename): def write(self, filename):