1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-22 14:28:07 +00:00

refactor(core): improve flash api by introducing flash_area_write_data function

[no changelog]
This commit is contained in:
tychovrahe 2024-03-13 16:33:33 +01:00 committed by TychoVrahe
parent 39cfa7087a
commit 89147ef493
12 changed files with 133 additions and 104 deletions

View File

@ -227,11 +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) / FLASH_BURST_SIZE; j++) { ensure(flash_area_write_data(&BOOTLOADER_AREA, 0, sdcard_buf,
ensure(flash_area_write_burst(&BOOTLOADER_AREA, j * FLASH_BURST_SIZE, IMAGE_HEADER_SIZE + codelen),
&sdcard_buf[j * FLASH_BURST_WORDS]),
NULL); NULL);
}
ensure(flash_lock_write(), NULL); ensure(flash_lock_write(), NULL);

View File

@ -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_BURST_SIZE == 0) * sectrue, NULL); ensure((chunk_size % FLASH_BLOCK_SIZE == 0) * sectrue, NULL);
while (bytes_remaining > 0) { while (bytes_remaining > 0) {
// erase flash before writing // erase flash before writing
@ -749,17 +749,15 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
// write the received data // write the received data
uint32_t bytes_to_write = MIN(bytes_erased, bytes_remaining); uint32_t bytes_to_write = MIN(bytes_erased, bytes_remaining);
uint32_t write_end = write_offset + bytes_to_write;
ensure(flash_unlock_write(), NULL); ensure(flash_unlock_write(), NULL);
while (write_offset < write_end) { ensure(flash_area_write_data(&FIRMWARE_AREA, write_offset, src,
// write a block to the flash bytes_to_write),
ensure(flash_area_write_burst(&FIRMWARE_AREA, write_offset, src), NULL); NULL);
write_offset += FLASH_BURST_SIZE;
src += FLASH_BURST_WORDS;
}
ensure(flash_lock_write(), NULL); ensure(flash_lock_write(), NULL);
write_offset += bytes_to_write;
src += bytes_to_write / sizeof(uint32_t);
bytes_remaining -= bytes_to_write; bytes_remaining -= bytes_to_write;
} }

View File

@ -217,27 +217,20 @@ void check_and_replace_bootloader(void) {
do { do {
uint32_t *p = decomp_out; uint32_t *p = decomp_out;
uint32_t last_whole_word_addr = (((uint32_t)decomp.dest) & ~0x7F); uint32_t size = decomp.dest - (uint8_t *)decomp_out;
while ((uint32_t)p < last_whole_word_addr) { uint32_t size_padded = FLASH_ALIGN(size);
ensure(flash_area_write_burst(&BOOTLOADER_AREA, offset, p), NULL); ensure(flash_area_write_data_padded(&BOOTLOADER_AREA, offset, p, size, 0,
p += FLASH_BURST_WORDS; size_padded),
offset += FLASH_BURST_WORDS * sizeof(uint32_t); NULL);
} offset += size_padded;
if ((uint8_t *)p < decomp.dest) {
// last few bytes in case of unaligned data
uint32_t d[FLASH_BURST_WORDS] = {0};
memcpy(&d, p, (uint32_t)decomp.dest - (uint32_t)p);
ensure(flash_area_write_burst(&BOOTLOADER_AREA, offset, d), NULL);
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_WORDS] = {0}; if (offset < bl_len) {
// fill the rest of the bootloader area with 0x00 // fill the rest of the bootloader area with 0x00
while (offset < bl_len) { ensure(flash_area_write_data_padded(&BOOTLOADER_AREA, offset, NULL, 0, 0,
ensure(flash_area_write_burst(&BOOTLOADER_AREA, offset, d), NULL); bl_len - offset),
offset += FLASH_BURST_WORDS * sizeof(uint32_t); NULL);
} }
ensure(flash_lock_write(), NULL); ensure(flash_lock_write(), NULL);

View File

@ -13,24 +13,10 @@ bool translations_write(const uint8_t* data, uint32_t offset, uint32_t len) {
} }
ensure(flash_unlock_write(), "translations_write unlock"); ensure(flash_unlock_write(), "translations_write unlock");
for (int i = 0; i < (len / FLASH_BLOCK_SIZE); i++) {
// todo consider alignment // todo consider alignment
ensure(flash_area_write_block(&TRANSLATIONS_AREA, ensure(flash_area_write_data_padded(&TRANSLATIONS_AREA, offset, data, len,
offset + (i * FLASH_BLOCK_SIZE), 0xFF, FLASH_ALIGN(len)),
(const uint32_t*)&data[i * FLASH_BLOCK_SIZE]),
"translations_write write"); "translations_write write");
}
if (len % FLASH_BLOCK_SIZE) {
flash_block_t block = {0};
memset(block, 0xFF, FLASH_BLOCK_SIZE);
memcpy(block, data + (len / FLASH_BLOCK_SIZE) * FLASH_BLOCK_SIZE,
len % FLASH_BLOCK_SIZE);
ensure(flash_area_write_block(
&TRANSLATIONS_AREA,
offset + (len / FLASH_BLOCK_SIZE) * FLASH_BLOCK_SIZE, block),
"translations_write write rest");
}
ensure(flash_lock_write(), "translations_write lock"); ensure(flash_lock_write(), "translations_write lock");
return true; return true;
} }

View File

@ -28,9 +28,6 @@
#include "flash_ll.h" #include "flash_ll.h"
#define FLASH_BURST_WORDS (4 * 8)
#define FLASH_BURST_SIZE (FLASH_BURST_WORDS * sizeof(uint32_t))
void flash_init(void); void flash_init(void);
#endif // TREZORHAL_FLASH_H #endif // TREZORHAL_FLASH_H

View File

@ -194,20 +194,6 @@ 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]);

View File

@ -130,22 +130,22 @@ secbool flash_sector_erase(uint16_t sector) {
secbool flash_write_quadword(uint16_t sector, uint32_t offset, secbool flash_write_quadword(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, 4 * sizeof(uint32_t)); (uint32_t)flash_get_address(sector, offset, FLASH_QUADWORD_SIZE);
if (address == 0) { if (address == 0) {
return secfalse; return secfalse;
} }
if (offset % (4 * sizeof(uint32_t))) { // we write only at 16-byte boundary if (offset % FLASH_QUADWORD_SIZE) { // we write only at 16-byte boundary
return secfalse; return secfalse;
} }
for (int i = 0; i < 4; i++) { for (int i = 0; i < FLASH_QUADWORD_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 < 4; i++) { for (int i = 0; i < FLASH_QUADWORD_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;
@ -160,7 +160,7 @@ secbool flash_write_quadword(uint16_t sector, uint32_t offset,
return secfalse; return secfalse;
} }
for (int i = 0; i < 4; i++) { for (int i = 0; i < FLASH_QUADWORD_WORDS; i++) {
if (data[i] != *((const uint32_t *)address + i)) { if (data[i] != *((const uint32_t *)address + i)) {
return secfalse; return secfalse;
} }
@ -175,7 +175,7 @@ secbool flash_write_burst(uint16_t sector, uint32_t offset,
if (address == 0) { if (address == 0) {
return secfalse; return secfalse;
} }
if (offset % FLASH_BURST_SIZE) { if (offset % FLASH_BURST_SIZE) { // we write only at 128-byte boundary
return secfalse; return secfalse;
} }

View File

@ -25,6 +25,12 @@
#define SENSITIVE __attribute__((section(".sensitive"))) #define SENSITIVE __attribute__((section(".sensitive")))
#define FLASH_QUADWORD_WORDS (4)
#define FLASH_QUADWORD_SIZE (FLASH_QUADWORD_WORDS * sizeof(uint32_t))
#define FLASH_BURST_WORDS (8 * FLASH_QUADWORD_WORDS)
#define FLASH_BURST_SIZE (FLASH_BURST_WORDS * sizeof(uint32_t))
typedef enum { typedef enum {
CLOCK_160_MHZ = 0, CLOCK_160_MHZ = 0,
} clock_settings_t; } clock_settings_t;

View File

@ -228,20 +228,6 @@ 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) *

View File

@ -26,9 +26,6 @@
#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] = {
@ -161,20 +158,6 @@ 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]);

View File

@ -18,7 +18,9 @@
*/ */
#include "flash_area.h" #include "flash_area.h"
#include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <string.h>
uint32_t flash_area_get_size(const flash_area_t *area) { uint32_t flash_area_get_size(const flash_area_t *area) {
uint32_t size = 0; uint32_t size = 0;
@ -120,6 +122,7 @@ secbool flash_area_write_quadword(const flash_area_t *area, uint32_t offset,
#endif // not defined FLASH_BIT_ACCESS #endif // not defined FLASH_BIT_ACCESS
#ifdef FLASH_BURST_SIZE
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;
@ -129,6 +132,7 @@ 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
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) {
@ -145,6 +149,81 @@ secbool flash_area_write_block(const flash_area_t *area, uint32_t offset,
return flash_write_block(sector, sector_offset, block); return flash_write_block(sector, sector_offset, block);
} }
secbool __wur flash_area_write_data(const flash_area_t *area, uint32_t offset,
const void *data, uint32_t size) {
return flash_area_write_data_padded(area, offset, data, size, 0, size);
}
secbool __wur flash_area_write_data_padded(const flash_area_t *area,
uint32_t offset, const void *data,
uint32_t data_size, uint8_t padding,
uint32_t total_size) {
if (offset % FLASH_BLOCK_SIZE) {
return secfalse;
}
if (total_size % FLASH_BLOCK_SIZE) {
return secfalse;
}
if (data_size > total_size) {
return secfalse;
}
if (offset + total_size > flash_area_get_size(area)) {
return secfalse;
}
const uint32_t *data32 = (const uint32_t *)data;
while (total_size > 0) {
#ifdef FLASH_BURST_SIZE
if ((offset % FLASH_BURST_SIZE) == 0 &&
(offset + FLASH_BURST_SIZE) <= total_size) {
if (data_size >= FLASH_BURST_SIZE) {
if (flash_area_write_burst(area, offset, data32) != sectrue) {
return secfalse;
}
data_size -= FLASH_BURST_SIZE;
data32 += FLASH_BURST_WORDS;
} else {
uint32_t burst[FLASH_BURST_WORDS];
memset(burst, padding, sizeof(burst));
if (data_size > 0) {
memcpy(burst, data32, data_size);
data_size = 0;
}
if (flash_area_write_burst(area, offset, burst) != sectrue) {
return secfalse;
}
}
offset += FLASH_BURST_SIZE;
total_size -= FLASH_BURST_SIZE;
} else
#endif
{
if (data_size >= FLASH_BLOCK_SIZE) {
if (flash_area_write_block(area, offset, data32) != sectrue) {
return secfalse;
}
data_size -= FLASH_BLOCK_SIZE;
data32 += FLASH_BLOCK_WORDS;
} else {
uint32_t block[FLASH_BLOCK_WORDS];
memset(block, padding, sizeof(block));
if (data_size > 0) {
memcpy(block, data32, data_size);
data_size = 0;
}
if (flash_area_write_block(area, offset, block) != sectrue) {
return secfalse;
}
}
offset += FLASH_BLOCK_SIZE;
total_size -= FLASH_BLOCK_SIZE;
}
}
return sectrue;
}
secbool flash_area_erase(const flash_area_t *area, secbool flash_area_erase(const flash_area_t *area,
void (*progress)(int pos, int len)) { void (*progress)(int pos, int len)) {
return flash_area_erase_bulk(area, 1, progress); return flash_area_erase_bulk(area, 1, progress);

View File

@ -76,6 +76,23 @@ secbool __wur flash_area_write_burst(const flash_area_t *area, uint32_t offset,
secbool __wur flash_area_write_block(const flash_area_t *area, uint32_t offset, secbool __wur flash_area_write_block(const flash_area_t *area, uint32_t offset,
const flash_block_t block); const flash_block_t block);
// Writes data to specified 'offset' inside a flash area
// Data is written in efficient way, using the smallest possible number of
// flash operations on the given architecture.
// Data and its size must be aligned to size of one flash block
secbool __wur flash_area_write_data(const flash_area_t *area, uint32_t offset,
const void *data, uint32_t size);
// Writes data to specified 'offset' inside a flash area
// Data is written in efficient way, using the smallest possible number of
// flash operations on the given architecture.
// Data and total size must be aligned to size of one flash block
// The difference between data_size and total_size is padded with 'padding'
secbool __wur flash_area_write_data_padded(const flash_area_t *area,
uint32_t offset, const void *data,
uint32_t data_size, uint8_t padding,
uint32_t total_size);
secbool __wur flash_area_erase(const flash_area_t *area, secbool __wur flash_area_erase(const flash_area_t *area,
void (*progress)(int pos, int len)); void (*progress)(int pos, int len));
secbool __wur flash_area_erase_bulk(const flash_area_t *area, int count, secbool __wur flash_area_erase_bulk(const flash_area_t *area, int count,