bootloader: check vendor header / image header before flashing

pull/25/head
Pavol Rusnak 7 years ago
parent 9690f1abdf
commit 36143033c4
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D

@ -10,9 +10,6 @@
#include "lowlevel.h"
#include "version.h"
#define BOOTLOADER_IMAGE_MAGIC 0x425A5254 // TRZB
#define BOOTLOADER_IMAGE_MAXSIZE (1 * 128 * 1024)
const uint8_t BOARDLOADER_KEY_M = 2;
const uint8_t BOARDLOADER_KEY_N = 3;
static const uint8_t * const BOARDLOADER_KEYS[] = {

@ -21,9 +21,6 @@
#include "messages.h"
#include "style.h"
#define FIRMWARE_IMAGE_MAGIC 0x465A5254 // TRZF
#define FIRMWARE_IMAGE_MAXSIZE (6 * 128 * 1024)
void display_fade(int start, int end, int delay)
{
for (int i = 0; i < 100; i++) {
@ -292,6 +289,11 @@ void check_bootloader_version(void)
ensure(sectrue * (0 == memcmp(bits, bits2, FLASH_OTP_BLOCK_SIZE)), "Bootloader downgraded");
}
secbool load_vendor_header_keys(const uint8_t * const data, vendor_header * const vhdr)
{
return load_vendor_header(data, BOOTLOADER_KEY_M, BOOTLOADER_KEY_N, BOOTLOADER_KEYS, vhdr);
}
int main(void)
{
#if PRODUCTION
@ -312,7 +314,7 @@ int main(void)
vendor_header vhdr;
// start the bootloader if user touched the screen or no firmware installed
secbool firmware_present = load_vendor_header((const uint8_t *)FIRMWARE_START, BOOTLOADER_KEY_M, BOOTLOADER_KEY_N, BOOTLOADER_KEYS, &vhdr);
secbool firmware_present = load_vendor_header_keys((const uint8_t *)FIRMWARE_START, &vhdr);
if (touched || firmware_present != sectrue) {
if (bootloader_loop(firmware_present) != sectrue) {
return 1;
@ -320,7 +322,7 @@ int main(void)
}
ensure(
load_vendor_header((const uint8_t *)FIRMWARE_START, BOOTLOADER_KEY_M, BOOTLOADER_KEY_N, BOOTLOADER_KEYS, &vhdr),
load_vendor_header_keys((const uint8_t *)FIRMWARE_START, &vhdr),
"invalid vendor header");
image_header hdr;

@ -227,7 +227,7 @@ void process_msg_Ping(uint8_t iface_num, uint32_t msg_size, uint8_t *buf)
MSG_SEND(Success);
}
static uint32_t firmware_remaining, firmware_flashed, chunk_requested;
static uint32_t firmware_remaining, firmware_block, chunk_requested;
static void progress_erase(int pos, int len)
{
@ -237,7 +237,7 @@ static void progress_erase(int pos, int len)
void process_msg_FirmwareErase(uint8_t iface_num, uint32_t msg_size, uint8_t *buf)
{
firmware_remaining = 0;
firmware_flashed = 0;
firmware_block = 0;
chunk_requested = 0;
MSG_RECV_INIT(FirmwareErase);
@ -304,7 +304,7 @@ static bool _read_payload(pb_istream_t *stream, const pb_field_t *field, void **
while (stream->bytes_left) {
// update loader
display_loader(250 + 750 * (firmware_flashed + chunk_written) / (firmware_flashed + firmware_remaining), 0, COLOR_BL_BLUE, COLOR_BLACK, 0, 0, 0);
display_loader(250 + 750 * (firmware_block * IMAGE_CHUNK_SIZE + chunk_written) / (firmware_block * IMAGE_CHUNK_SIZE + firmware_remaining), 0, COLOR_BL_BLUE, COLOR_BLACK, 0, 0, 0);
// read data
if (!pb_read(stream, (pb_byte_t *)(chunk_buffer + chunk_written), (stream->bytes_left > BUFSIZE) ? BUFSIZE : stream->bytes_left)) {
chunk_size = 0;
@ -316,6 +316,10 @@ static bool _read_payload(pb_istream_t *stream, const pb_field_t *field, void **
return true;
}
static image_header hdr;
extern secbool load_vendor_header_keys(const uint8_t * const data, vendor_header * const vhdr);
int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, uint8_t *buf)
{
MSG_RECV_INIT(FirmwareUpload);
@ -327,6 +331,25 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, uint8_t *bu
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_DataError);
MSG_SEND_ASSIGN_STRING(message, "Invalid chunk size");
MSG_SEND(Failure);
return -1;
}
if (firmware_block == 0) {
vendor_header vhdr;
if (sectrue != load_vendor_header_keys(chunk_buffer, &vhdr)) {
MSG_SEND_INIT(Failure);
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Invalid vendor header");
MSG_SEND(Failure);
return -2;
}
if (sectrue != load_image_header(chunk_buffer + vhdr.hdrlen, FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE, vhdr.vsig_m, vhdr.vsig_n, vhdr.vpub, &hdr)) {
MSG_SEND_INIT(Failure);
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Invalid firmware header");
MSG_SEND(Failure);
return -3;
}
}
if (sectrue != flash_unlock()) {
@ -334,24 +357,31 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, uint8_t *bu
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Could not unlock flash");
MSG_SEND(Failure);
return -1;
return -4;
}
// TODO: don't use firmware_flashed, but block index, so we can fill into non-continous area
// TODO: fix writing to non-continous area
const uint32_t * const src = (const uint32_t * const)chunk_buffer;
for (int i = 0; i < chunk_size / sizeof(uint32_t); i++) {
ensure(flash_write_word(FIRMWARE_START + firmware_flashed + i * sizeof(uint32_t), src[i]), NULL);
if (sectrue != flash_write_word(FIRMWARE_START + firmware_block * IMAGE_CHUNK_SIZE + i * sizeof(uint32_t), src[i])) {
MSG_SEND_INIT(Failure);
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Could not write data");
MSG_SEND(Failure);
flash_lock();
return -5;
}
}
flash_lock();
firmware_remaining -= chunk_requested;
firmware_flashed += chunk_requested;
firmware_block++;
if (firmware_remaining > 0) {
chunk_requested = (firmware_remaining > IMAGE_CHUNK_SIZE) ? IMAGE_CHUNK_SIZE : firmware_remaining;
MSG_SEND_INIT(FirmwareRequest);
MSG_SEND_ASSIGN_VALUE(offset, firmware_flashed);
MSG_SEND_ASSIGN_VALUE(offset, firmware_block * IMAGE_CHUNK_SIZE);
MSG_SEND_ASSIGN_VALUE(length, chunk_requested);
MSG_SEND(FirmwareRequest);
} else {

@ -12,6 +12,12 @@
#define IMAGE_SIG_SIZE 65
#define IMAGE_CHUNK_SIZE (128 * 1024)
#define BOOTLOADER_IMAGE_MAGIC 0x425A5254 // TRZB
#define BOOTLOADER_IMAGE_MAXSIZE (1 * 128 * 1024)
#define FIRMWARE_IMAGE_MAGIC 0x465A5254 // TRZF
#define FIRMWARE_IMAGE_MAXSIZE (6 * 128 * 1024)
typedef struct {
uint32_t magic;
uint32_t hdrlen;

Loading…
Cancel
Save