1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-22 23:48:12 +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 "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;
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();
return;
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();
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;

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));
}
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);

View File

@ -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

Binary file not shown.

View File

@ -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):