mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-18 04:18:10 +00:00
feat(core): use flash bursts for faster flashing
[no changelog]
This commit is contained in:
parent
e1161866da
commit
70a673fabc
@ -227,12 +227,9 @@ static secbool copy_sdcard(void) {
|
|||||||
// copy bootloader from SD card to Flash
|
// copy bootloader from SD card to Flash
|
||||||
term_printf("copying new bootloader from SD card\n\n");
|
term_printf("copying new bootloader from SD card\n\n");
|
||||||
|
|
||||||
for (int j = 0; j < (IMAGE_HEADER_SIZE + codelen) /
|
for (int j = 0; j < (IMAGE_HEADER_SIZE + codelen) / FLASH_BURST_SIZE; j++) {
|
||||||
(FLASH_BURST_LENGTH * sizeof(uint32_t));
|
ensure(flash_area_write_burst(&BOOTLOADER_AREA, j * FLASH_BURST_SIZE,
|
||||||
j++) {
|
&sdcard_buf[j * FLASH_BURST_WORDS]),
|
||||||
ensure(flash_area_write_burst(&BOOTLOADER_AREA,
|
|
||||||
j * FLASH_BURST_LENGTH * sizeof(uint32_t),
|
|
||||||
&sdcard_buf[j * FLASH_BURST_LENGTH]),
|
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -730,7 +730,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
|
|||||||
// offset into the FIRMWARE_AREA part of the flash
|
// offset into the FIRMWARE_AREA part of the flash
|
||||||
uint32_t write_offset = firmware_block * IMAGE_CHUNK_SIZE;
|
uint32_t write_offset = firmware_block * IMAGE_CHUNK_SIZE;
|
||||||
|
|
||||||
ensure((chunk_size % FLASH_BLOCK_SIZE == 0) * sectrue, NULL);
|
ensure((chunk_size % FLASH_BURST_SIZE == 0) * sectrue, NULL);
|
||||||
|
|
||||||
while (bytes_remaining > 0) {
|
while (bytes_remaining > 0) {
|
||||||
// erase flash before writing
|
// erase flash before writing
|
||||||
@ -754,9 +754,9 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
|
|||||||
ensure(flash_unlock_write(), NULL);
|
ensure(flash_unlock_write(), NULL);
|
||||||
while (write_offset < write_end) {
|
while (write_offset < write_end) {
|
||||||
// write a block to the flash
|
// write a block to the flash
|
||||||
ensure(flash_area_write_block(&FIRMWARE_AREA, write_offset, src), NULL);
|
ensure(flash_area_write_burst(&FIRMWARE_AREA, write_offset, src), NULL);
|
||||||
write_offset += FLASH_BLOCK_SIZE;
|
write_offset += FLASH_BURST_SIZE;
|
||||||
src += FLASH_BLOCK_WORDS;
|
src += FLASH_BURST_WORDS;
|
||||||
}
|
}
|
||||||
ensure(flash_lock_write(), NULL);
|
ensure(flash_lock_write(), NULL);
|
||||||
|
|
||||||
|
@ -220,24 +220,24 @@ void check_and_replace_bootloader(void) {
|
|||||||
uint32_t last_whole_word_addr = (((uint32_t)decomp.dest) & ~0x7F);
|
uint32_t last_whole_word_addr = (((uint32_t)decomp.dest) & ~0x7F);
|
||||||
while ((uint32_t)p < last_whole_word_addr) {
|
while ((uint32_t)p < last_whole_word_addr) {
|
||||||
ensure(flash_area_write_burst(&BOOTLOADER_AREA, offset, p), NULL);
|
ensure(flash_area_write_burst(&BOOTLOADER_AREA, offset, p), NULL);
|
||||||
p += FLASH_BURST_LENGTH;
|
p += FLASH_BURST_WORDS;
|
||||||
offset += FLASH_BURST_LENGTH * sizeof(uint32_t);
|
offset += FLASH_BURST_WORDS * sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
if ((uint8_t *)p < decomp.dest) {
|
if ((uint8_t *)p < decomp.dest) {
|
||||||
// last few bytes in case of unaligned data
|
// last few bytes in case of unaligned data
|
||||||
uint32_t d[FLASH_BURST_LENGTH] = {0};
|
uint32_t d[FLASH_BURST_WORDS] = {0};
|
||||||
memcpy(&d, p, (uint32_t)decomp.dest - (uint32_t)p);
|
memcpy(&d, p, (uint32_t)decomp.dest - (uint32_t)p);
|
||||||
ensure(flash_area_write_burst(&BOOTLOADER_AREA, offset, d), NULL);
|
ensure(flash_area_write_burst(&BOOTLOADER_AREA, offset, d), NULL);
|
||||||
offset += FLASH_BURST_LENGTH * sizeof(uint32_t);
|
offset += FLASH_BURST_WORDS * sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
decomp.dest = (uint8_t *)decomp_out;
|
decomp.dest = (uint8_t *)decomp_out;
|
||||||
} while (uzlib_uncompress(&decomp) >= 0);
|
} while (uzlib_uncompress(&decomp) >= 0);
|
||||||
|
|
||||||
uint32_t d[FLASH_BURST_LENGTH] = {0};
|
uint32_t d[FLASH_BURST_WORDS] = {0};
|
||||||
// fill the rest of the bootloader area with 0x00
|
// fill the rest of the bootloader area with 0x00
|
||||||
while (offset < bl_len) {
|
while (offset < bl_len) {
|
||||||
ensure(flash_area_write_burst(&BOOTLOADER_AREA, offset, d), NULL);
|
ensure(flash_area_write_burst(&BOOTLOADER_AREA, offset, d), NULL);
|
||||||
offset += FLASH_BURST_LENGTH * sizeof(uint32_t);
|
offset += FLASH_BURST_WORDS * sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
ensure(flash_lock_write(), NULL);
|
ensure(flash_lock_write(), NULL);
|
||||||
|
@ -28,7 +28,8 @@
|
|||||||
|
|
||||||
#include "flash_ll.h"
|
#include "flash_ll.h"
|
||||||
|
|
||||||
#define FLASH_BURST_LENGTH (4 * 8)
|
#define FLASH_BURST_WORDS (4 * 8)
|
||||||
|
#define FLASH_BURST_SIZE (FLASH_BURST_WORDS * sizeof(uint32_t))
|
||||||
|
|
||||||
void flash_init(void);
|
void flash_init(void);
|
||||||
|
|
||||||
|
@ -194,6 +194,20 @@ secbool flash_write_word(uint16_t sector, uint32_t offset, uint32_t data) {
|
|||||||
return sectrue;
|
return sectrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
secbool flash_write_burst(uint16_t sector, uint32_t offset,
|
||||||
|
const uint32_t *data) {
|
||||||
|
if ((offset % FLASH_BURST_SIZE) != 0) {
|
||||||
|
return secfalse;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < FLASH_BURST_WORDS; i++) {
|
||||||
|
if (sectrue !=
|
||||||
|
flash_write_word(sector, offset + i * sizeof(uint32_t), data[i])) {
|
||||||
|
return secfalse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sectrue;
|
||||||
|
}
|
||||||
|
|
||||||
secbool flash_write_block(uint16_t sector, uint32_t offset,
|
secbool flash_write_block(uint16_t sector, uint32_t offset,
|
||||||
const flash_block_t block) {
|
const flash_block_t block) {
|
||||||
return flash_write_word(sector, offset, block[0]);
|
return flash_write_word(sector, offset, block[0]);
|
||||||
|
@ -171,23 +171,22 @@ secbool flash_write_quadword(uint16_t sector, uint32_t offset,
|
|||||||
secbool flash_write_burst(uint16_t sector, uint32_t offset,
|
secbool flash_write_burst(uint16_t sector, uint32_t offset,
|
||||||
const uint32_t *data) {
|
const uint32_t *data) {
|
||||||
uint32_t address =
|
uint32_t address =
|
||||||
(uint32_t)flash_get_address(sector, offset, 8 * 4 * sizeof(uint32_t));
|
(uint32_t)flash_get_address(sector, offset, FLASH_BURST_SIZE);
|
||||||
if (address == 0) {
|
if (address == 0) {
|
||||||
return secfalse;
|
return secfalse;
|
||||||
}
|
}
|
||||||
if (offset %
|
if (offset % FLASH_BURST_SIZE) {
|
||||||
(8 * 4 * sizeof(uint32_t))) { // we write only at 16-byte boundary
|
|
||||||
return secfalse;
|
return secfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 8 * 4; i++) {
|
for (int i = 0; i < FLASH_BURST_WORDS; i++) {
|
||||||
if (data[i] != (data[i] & *((const uint32_t *)address + i))) {
|
if (data[i] != (data[i] & *((const uint32_t *)address + i))) {
|
||||||
return secfalse;
|
return secfalse;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
secbool all_match = sectrue;
|
secbool all_match = sectrue;
|
||||||
for (int i = 0; i < 8 * 4; i++) {
|
for (int i = 0; i < FLASH_BURST_WORDS; i++) {
|
||||||
if (data[i] != *((const uint32_t *)address + i)) {
|
if (data[i] != *((const uint32_t *)address + i)) {
|
||||||
all_match = secfalse;
|
all_match = secfalse;
|
||||||
break;
|
break;
|
||||||
@ -202,7 +201,7 @@ secbool flash_write_burst(uint16_t sector, uint32_t offset,
|
|||||||
return secfalse;
|
return secfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 8 * 4; i++) {
|
for (int i = 0; i < FLASH_BURST_WORDS; i++) {
|
||||||
if (data[i] != *((const uint32_t *)address + i)) {
|
if (data[i] != *((const uint32_t *)address + i)) {
|
||||||
return secfalse;
|
return secfalse;
|
||||||
}
|
}
|
||||||
|
@ -228,6 +228,20 @@ secbool flash_write_word(uint16_t sector, uint32_t offset, uint32_t data) {
|
|||||||
return sectrue;
|
return sectrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
secbool flash_write_burst(uint16_t sector, uint32_t offset,
|
||||||
|
const uint32_t *data) {
|
||||||
|
if ((offset % FLASH_BURST_SIZE) != 0) {
|
||||||
|
return secfalse;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < FLASH_BURST_WORDS; i++) {
|
||||||
|
if (sectrue !=
|
||||||
|
flash_write_word(sector, offset + i * sizeof(uint32_t), data[i])) {
|
||||||
|
return secfalse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sectrue;
|
||||||
|
}
|
||||||
|
|
||||||
secbool flash_write_block(uint16_t sector, uint32_t offset,
|
secbool flash_write_block(uint16_t sector, uint32_t offset,
|
||||||
const flash_block_t block) {
|
const flash_block_t block) {
|
||||||
if (offset % (sizeof(uint32_t) *
|
if (offset % (sizeof(uint32_t) *
|
||||||
|
@ -26,6 +26,9 @@
|
|||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "supervise.h"
|
#include "supervise.h"
|
||||||
|
|
||||||
|
#define FLASH_BURST_WORDS (4 * 8)
|
||||||
|
#define FLASH_BURST_SIZE (FLASH_BURST_WORDS * sizeof(uint32_t))
|
||||||
|
|
||||||
#define STORAGE_AREAS_COUNT 2
|
#define STORAGE_AREAS_COUNT 2
|
||||||
|
|
||||||
static const uint32_t FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT + 1] = {
|
static const uint32_t FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT + 1] = {
|
||||||
@ -158,6 +161,20 @@ secbool flash_write_word(uint16_t sector, uint32_t offset, uint32_t data) {
|
|||||||
return sectrue;
|
return sectrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
secbool flash_write_burst(uint16_t sector, uint32_t offset,
|
||||||
|
const uint32_t *data) {
|
||||||
|
if ((offset % FLASH_BURST_SIZE) != 0) {
|
||||||
|
return secfalse;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < FLASH_BURST_WORDS; i++) {
|
||||||
|
if (sectrue !=
|
||||||
|
flash_write_word(sector, offset + i * sizeof(uint32_t), data[i])) {
|
||||||
|
return secfalse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sectrue;
|
||||||
|
}
|
||||||
|
|
||||||
secbool flash_write_block(uint16_t sector, uint32_t offset,
|
secbool flash_write_block(uint16_t sector, uint32_t offset,
|
||||||
const flash_block_t block) {
|
const flash_block_t block) {
|
||||||
return flash_write_word(sector, offset, block[0]);
|
return flash_write_word(sector, offset, block[0]);
|
||||||
|
@ -106,20 +106,6 @@ secbool flash_area_write_word(const flash_area_t *area, uint32_t offset,
|
|||||||
return flash_write_word(sector, sector_offset, data);
|
return flash_write_word(sector, sector_offset, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
secbool flash_area_write_burst(const flash_area_t *area, uint32_t offset,
|
|
||||||
const uint32_t *data) {
|
|
||||||
if (offset % (8 * 16) != 0) {
|
|
||||||
return secfalse;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < (8 * 4); i++) {
|
|
||||||
if (sectrue !=
|
|
||||||
flash_area_write_word(area, offset + i * sizeof(uint32_t), data[i])) {
|
|
||||||
return secfalse;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sectrue;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else // not defined FLASH_BIT_ACCESS
|
#else // not defined FLASH_BIT_ACCESS
|
||||||
|
|
||||||
secbool flash_area_write_quadword(const flash_area_t *area, uint32_t offset,
|
secbool flash_area_write_quadword(const flash_area_t *area, uint32_t offset,
|
||||||
@ -132,6 +118,8 @@ secbool flash_area_write_quadword(const flash_area_t *area, uint32_t offset,
|
|||||||
return flash_write_quadword(sector, sector_offset, data);
|
return flash_write_quadword(sector, sector_offset, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // not defined FLASH_BIT_ACCESS
|
||||||
|
|
||||||
secbool flash_area_write_burst(const flash_area_t *area, uint32_t offset,
|
secbool flash_area_write_burst(const flash_area_t *area, uint32_t offset,
|
||||||
const uint32_t *data) {
|
const uint32_t *data) {
|
||||||
uint16_t sector;
|
uint16_t sector;
|
||||||
@ -142,8 +130,6 @@ secbool flash_area_write_burst(const flash_area_t *area, uint32_t offset,
|
|||||||
return flash_write_burst(sector, sector_offset, data);
|
return flash_write_burst(sector, sector_offset, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // not defined FLASH_BIT_ACCESS
|
|
||||||
|
|
||||||
secbool flash_area_write_block(const flash_area_t *area, uint32_t offset,
|
secbool flash_area_write_block(const flash_area_t *area, uint32_t offset,
|
||||||
const flash_block_t block) {
|
const flash_block_t block) {
|
||||||
if (!FLASH_IS_ALIGNED(offset)) {
|
if (!FLASH_IS_ALIGNED(offset)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user