mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-06-27 18:32:34 +00:00
136 lines
3.4 KiB
C
136 lines
3.4 KiB
C
/*
|
|
* This file is part of the Trezor project, https://trezor.io/
|
|
*
|
|
* Copyright (c) SatoshiLabs
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "common.h"
|
|
#include TREZOR_BOARD
|
|
#include "ble_hal.h"
|
|
#include "common.h"
|
|
#include "dfu.h"
|
|
#include "fwu.h"
|
|
|
|
static TFwu sFwu;
|
|
|
|
static uint32_t tick_start = 0;
|
|
|
|
void txFunction(struct SFwu *fwu, uint8_t *buf, uint8_t len);
|
|
static uint8_t readData(uint8_t *data, int maxLen);
|
|
|
|
void dfu_init(void) {}
|
|
|
|
dfu_result_t dfu_update_process(void) {
|
|
while (1) {
|
|
// Can send 4 chars...
|
|
// (On a microcontroller, you'd use the TX Empty interrupt or test a
|
|
// register.)
|
|
|
|
fwuCanSendData(&sFwu, 4);
|
|
|
|
// Data available? Get up to 4 bytes...
|
|
// (On a microcontroller, you'd use the RX Available interrupt or test a
|
|
// register.)
|
|
uint8_t rxBuf[4];
|
|
uint8_t rxLen = readData(rxBuf, 4);
|
|
if (rxLen > 0) {
|
|
fwuDidReceiveData(&sFwu, rxBuf, rxLen);
|
|
}
|
|
|
|
// Give the firmware update module a timeslot to continue the process.
|
|
EFwuProcessStatus status = fwuYield(&sFwu, 0);
|
|
|
|
if (status == FWU_STATUS_COMPLETION) {
|
|
ble_reset();
|
|
return DFU_SUCCESS;
|
|
}
|
|
|
|
if (status == FWU_STATUS_FAILURE) {
|
|
return DFU_FAIL;
|
|
}
|
|
|
|
if (hal_ticks_ms() - tick_start > 2000) {
|
|
return DFU_FAIL;
|
|
}
|
|
|
|
if (fwuIsReadyForChunk(&sFwu)) {
|
|
return DFU_NEXT_CHUNK;
|
|
}
|
|
}
|
|
}
|
|
|
|
dfu_result_t dfu_update_init(uint8_t *data, uint32_t len, uint32_t binary_len) {
|
|
sFwu.commandObject = data;
|
|
sFwu.commandObjectLen = len;
|
|
sFwu.dataObject = NULL;
|
|
sFwu.dataObjectLen = binary_len;
|
|
sFwu.txFunction = txFunction;
|
|
sFwu.responseTimeoutMillisec = 2000;
|
|
|
|
if (!ble_reset_to_bootloader()) {
|
|
return DFU_FAIL;
|
|
}
|
|
|
|
tick_start = hal_ticks_ms();
|
|
|
|
// Prepare the firmware update process.
|
|
fwuInit(&sFwu);
|
|
|
|
// Start the firmware update process.
|
|
fwuExec(&sFwu);
|
|
|
|
return dfu_update_process();
|
|
}
|
|
|
|
dfu_result_t dfu_update_chunk(uint8_t *data, uint32_t len) {
|
|
tick_start = hal_ticks_ms();
|
|
|
|
fwuSendChunk(&sFwu, data, len);
|
|
|
|
return dfu_update_process();
|
|
}
|
|
|
|
dfu_result_t dfu_update_do(uint8_t *datfile, uint32_t datfile_len,
|
|
uint8_t *binfile, uint32_t binfile_len) {
|
|
uint32_t chunk_offset = 0;
|
|
uint32_t rem_data = binfile_len;
|
|
|
|
dfu_result_t res = dfu_update_init(datfile, datfile_len, binfile_len);
|
|
|
|
while (res == DFU_NEXT_CHUNK) {
|
|
// Send the next chunk of the data object.
|
|
uint32_t chunk_size = 4096;
|
|
if (rem_data < 4096) {
|
|
chunk_size = rem_data;
|
|
rem_data = 0;
|
|
} else {
|
|
rem_data -= 4096;
|
|
}
|
|
res = dfu_update_chunk(&binfile[chunk_offset], chunk_size);
|
|
chunk_offset += chunk_size;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
void txFunction(struct SFwu *fwu, uint8_t *buf, uint8_t len) {
|
|
ble_comm_send(buf, len);
|
|
}
|
|
|
|
static uint8_t readData(uint8_t *data, int maxLen) {
|
|
return ble_comm_receive(data, maxLen);
|
|
}
|