1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-24 23:38:09 +00:00

Merge pull request #830 from trezor/tsusanka/fw-upgrade

FW Update: Request a small chunk first to make the UI smoother
This commit is contained in:
Pavol Rusnak 2020-02-15 13:08:33 +01:00 committed by GitHub
commit 2958a97c87
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 100 additions and 71 deletions

View File

@ -246,8 +246,11 @@ static secbool _recv_msg(uint8_t iface_num, uint32_t msg_size, uint8_t *buf,
} }
#define MSG_RECV_INIT(TYPE) TYPE msg_recv = TYPE##_init_default #define MSG_RECV_INIT(TYPE) TYPE msg_recv = TYPE##_init_default
#define MSG_RECV_CALLBACK(FIELD, CALLBACK) \ #define MSG_RECV_CALLBACK(FIELD, CALLBACK, ARGUMENT) \
{ msg_recv.FIELD.funcs.decode = &CALLBACK; } { \
msg_recv.FIELD.funcs.decode = &CALLBACK; \
msg_recv.FIELD.arg = (void *)ARGUMENT; \
}
#define MSG_RECV(TYPE) \ #define MSG_RECV(TYPE) \
_recv_msg(iface_num, msg_size, buf, TYPE##_fields, &msg_recv) _recv_msg(iface_num, msg_size, buf, TYPE##_fields, &msg_recv)
@ -324,8 +327,8 @@ void process_msg_FirmwareErase(uint8_t iface_num, uint32_t msg_size,
((firmware_remaining % sizeof(uint32_t)) == 0) && ((firmware_remaining % sizeof(uint32_t)) == 0) &&
(firmware_remaining <= (FIRMWARE_SECTORS_COUNT * IMAGE_CHUNK_SIZE))) { (firmware_remaining <= (FIRMWARE_SECTORS_COUNT * IMAGE_CHUNK_SIZE))) {
// request new firmware // request new firmware
chunk_requested = (firmware_remaining > IMAGE_CHUNK_SIZE) chunk_requested = (firmware_remaining > IMAGE_INIT_CHUNK_SIZE)
? IMAGE_CHUNK_SIZE ? IMAGE_INIT_CHUNK_SIZE
: firmware_remaining; : firmware_remaining;
MSG_SEND_INIT(FirmwareRequest); MSG_SEND_INIT(FirmwareRequest);
MSG_SEND_ASSIGN_VALUE(offset, 0); MSG_SEND_ASSIGN_VALUE(offset, 0);
@ -349,16 +352,20 @@ static bool _read_payload(pb_istream_t *stream, const pb_field_t *field,
void **arg) { void **arg) {
#define BUFSIZE 32768 #define BUFSIZE 32768
uint32_t offset = (uint32_t)(*arg);
if (stream->bytes_left > IMAGE_CHUNK_SIZE) { if (stream->bytes_left > IMAGE_CHUNK_SIZE) {
chunk_size = 0; chunk_size = 0;
return false; return false;
} }
if (offset == 0) {
// clear chunk buffer // clear chunk buffer
memset(chunk_buffer, 0xFF, IMAGE_CHUNK_SIZE); memset(chunk_buffer, 0xFF, IMAGE_CHUNK_SIZE);
}
uint32_t chunk_written = 0; uint32_t chunk_written = offset;
chunk_size = stream->bytes_left; chunk_size = offset + stream->bytes_left;
while (stream->bytes_left) { while (stream->bytes_left) {
// update loader but skip first block // update loader but skip first block
@ -432,14 +439,16 @@ static void detect_installation(vendor_header *current_vhdr,
} }
static int firmware_upload_chunk_retry = FIRMWARE_UPLOAD_CHUNK_RETRY_COUNT; static int firmware_upload_chunk_retry = FIRMWARE_UPLOAD_CHUNK_RETRY_COUNT;
static uint32_t headers_offset = 0;
static uint32_t read_offset = 0;
int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
uint8_t *buf) { uint8_t *buf) {
MSG_RECV_INIT(FirmwareUpload); MSG_RECV_INIT(FirmwareUpload);
MSG_RECV_CALLBACK(payload, _read_payload); MSG_RECV_CALLBACK(payload, _read_payload, read_offset);
secbool r = MSG_RECV(FirmwareUpload); secbool r = MSG_RECV(FirmwareUpload);
if (sectrue != r || chunk_size != chunk_requested) { if (sectrue != r || chunk_size != (chunk_requested + read_offset)) {
MSG_SEND_INIT(Failure); MSG_SEND_INIT(Failure);
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_DataError); MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_DataError);
MSG_SEND_ASSIGN_STRING(message, "Invalid chunk size"); MSG_SEND_ASSIGN_STRING(message, "Invalid chunk size");
@ -448,9 +457,11 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
} }
static image_header hdr; static image_header hdr;
secbool is_upgrade = secfalse;
uint32_t firstskip = 0;
if (firmware_block == 0) { if (firmware_block == 0) {
if (headers_offset == 0) {
// first block and headers are not yet parsed
vendor_header vhdr; vendor_header vhdr;
if (sectrue != load_vendor_header_keys(chunk_buffer, &vhdr)) { if (sectrue != load_vendor_header_keys(chunk_buffer, &vhdr)) {
MSG_SEND_INIT(Failure); MSG_SEND_INIT(Failure);
@ -472,7 +483,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
vendor_header current_vhdr; vendor_header current_vhdr;
image_header current_hdr; image_header current_hdr;
secbool is_new = secfalse, is_upgrade = secfalse; secbool is_new = secfalse;
detect_installation(&current_vhdr, &current_hdr, &vhdr, &hdr, &is_new, detect_installation(&current_vhdr, &current_hdr, &vhdr, &hdr, &is_new,
&is_upgrade); &is_upgrade);
@ -502,20 +513,36 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
return -4; return -4;
} }
headers_offset = IMAGE_HEADER_SIZE + vhdr.hdrlen;
read_offset = IMAGE_INIT_CHUNK_SIZE;
// request the rest of the first chunk
MSG_SEND_INIT(FirmwareRequest);
chunk_requested = IMAGE_CHUNK_SIZE - read_offset;
MSG_SEND_ASSIGN_VALUE(offset, read_offset);
MSG_SEND_ASSIGN_VALUE(length, chunk_requested);
MSG_SEND(FirmwareRequest);
firmware_remaining -= read_offset;
return (int)firmware_remaining;
} else {
// first block with the headers parsed -> the first chunk is now complete
read_offset = 0;
ui_fadeout(); ui_fadeout();
ui_screen_install(); ui_screen_install();
ui_fadein(); ui_fadein();
// if firmware is not upgrade, erase storage // if firmware is not upgrade, erase storage
if (sectrue != is_upgrade) { if (sectrue != is_upgrade) {
ensure(flash_erase_sectors(STORAGE_SECTORS, STORAGE_SECTORS_COUNT, NULL), ensure(
flash_erase_sectors(STORAGE_SECTORS, STORAGE_SECTORS_COUNT, NULL),
NULL); NULL);
} }
ensure(flash_erase_sectors(FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT, ensure(flash_erase_sectors(FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT,
ui_screen_install_progress_erase), ui_screen_install_progress_erase),
NULL); NULL);
}
firstskip = IMAGE_HEADER_SIZE + vhdr.hdrlen;
} }
// should not happen, but double-check // should not happen, but double-check
@ -528,8 +555,8 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
} }
if (sectrue != check_single_hash(hdr.hashes + firmware_block * 32, if (sectrue != check_single_hash(hdr.hashes + firmware_block * 32,
chunk_buffer + firstskip, chunk_buffer + headers_offset,
chunk_size - firstskip)) { chunk_size - headers_offset)) {
if (firmware_upload_chunk_retry > 0) { if (firmware_upload_chunk_retry > 0) {
--firmware_upload_chunk_retry; --firmware_upload_chunk_retry;
MSG_SEND_INIT(FirmwareRequest); MSG_SEND_INIT(FirmwareRequest);
@ -557,6 +584,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
ensure(flash_lock_write(), NULL); ensure(flash_lock_write(), NULL);
headers_offset = 0;
firmware_remaining -= chunk_requested; firmware_remaining -= chunk_requested;
firmware_block++; firmware_block++;
firmware_upload_chunk_retry = FIRMWARE_UPLOAD_CHUNK_RETRY_COUNT; firmware_upload_chunk_retry = FIRMWARE_UPLOAD_CHUNK_RETRY_COUNT;

View File

@ -27,9 +27,10 @@
#define BOOTLOADER_START 0x08020000 #define BOOTLOADER_START 0x08020000
#define FIRMWARE_START 0x08040000 #define FIRMWARE_START 0x08040000
#define IMAGE_HEADER_SIZE 0x400 #define IMAGE_HEADER_SIZE 0x400 // size of the bootloader or firmware header
#define IMAGE_SIG_SIZE 65 #define IMAGE_SIG_SIZE 65
#define IMAGE_CHUNK_SIZE (128 * 1024) #define IMAGE_CHUNK_SIZE (128 * 1024)
#define IMAGE_INIT_CHUNK_SIZE (16 * 1024)
#define BOOTLOADER_IMAGE_MAGIC 0x425A5254 // TRZB #define BOOTLOADER_IMAGE_MAGIC 0x425A5254 // TRZB
#define BOOTLOADER_IMAGE_MAXSIZE (BOOTLOADER_SECTORS_COUNT * IMAGE_CHUNK_SIZE) #define BOOTLOADER_IMAGE_MAXSIZE (BOOTLOADER_SECTORS_COUNT * IMAGE_CHUNK_SIZE)