mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-22 06:18:07 +00:00
refactor(core): improve flash api by introducing flash_area_write_data function
[no changelog]
This commit is contained in:
parent
39cfa7087a
commit
89147ef493
@ -227,11 +227,9 @@ static secbool copy_sdcard(void) {
|
||||
// copy bootloader from SD card to Flash
|
||||
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_burst(&BOOTLOADER_AREA, j * FLASH_BURST_SIZE,
|
||||
&sdcard_buf[j * FLASH_BURST_WORDS]),
|
||||
NULL);
|
||||
}
|
||||
ensure(flash_area_write_data(&BOOTLOADER_AREA, 0, sdcard_buf,
|
||||
IMAGE_HEADER_SIZE + codelen),
|
||||
NULL);
|
||||
|
||||
ensure(flash_lock_write(), 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
|
||||
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) {
|
||||
// erase flash before writing
|
||||
@ -749,17 +749,15 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
|
||||
|
||||
// write the received data
|
||||
uint32_t bytes_to_write = MIN(bytes_erased, bytes_remaining);
|
||||
uint32_t write_end = write_offset + bytes_to_write;
|
||||
|
||||
ensure(flash_unlock_write(), NULL);
|
||||
while (write_offset < write_end) {
|
||||
// write a block to the flash
|
||||
ensure(flash_area_write_burst(&FIRMWARE_AREA, write_offset, src), NULL);
|
||||
write_offset += FLASH_BURST_SIZE;
|
||||
src += FLASH_BURST_WORDS;
|
||||
}
|
||||
ensure(flash_area_write_data(&FIRMWARE_AREA, write_offset, src,
|
||||
bytes_to_write),
|
||||
NULL);
|
||||
ensure(flash_lock_write(), NULL);
|
||||
|
||||
write_offset += bytes_to_write;
|
||||
src += bytes_to_write / sizeof(uint32_t);
|
||||
|
||||
bytes_remaining -= bytes_to_write;
|
||||
}
|
||||
|
||||
|
@ -217,27 +217,20 @@ void check_and_replace_bootloader(void) {
|
||||
|
||||
do {
|
||||
uint32_t *p = decomp_out;
|
||||
uint32_t last_whole_word_addr = (((uint32_t)decomp.dest) & ~0x7F);
|
||||
while ((uint32_t)p < last_whole_word_addr) {
|
||||
ensure(flash_area_write_burst(&BOOTLOADER_AREA, offset, p), NULL);
|
||||
p += FLASH_BURST_WORDS;
|
||||
offset += FLASH_BURST_WORDS * sizeof(uint32_t);
|
||||
}
|
||||
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);
|
||||
}
|
||||
uint32_t size = decomp.dest - (uint8_t *)decomp_out;
|
||||
uint32_t size_padded = FLASH_ALIGN(size);
|
||||
ensure(flash_area_write_data_padded(&BOOTLOADER_AREA, offset, p, size, 0,
|
||||
size_padded),
|
||||
NULL);
|
||||
offset += size_padded;
|
||||
decomp.dest = (uint8_t *)decomp_out;
|
||||
} while (uzlib_uncompress(&decomp) >= 0);
|
||||
|
||||
uint32_t d[FLASH_BURST_WORDS] = {0};
|
||||
// fill the rest of the bootloader area with 0x00
|
||||
while (offset < bl_len) {
|
||||
ensure(flash_area_write_burst(&BOOTLOADER_AREA, offset, d), NULL);
|
||||
offset += FLASH_BURST_WORDS * sizeof(uint32_t);
|
||||
if (offset < bl_len) {
|
||||
// fill the rest of the bootloader area with 0x00
|
||||
ensure(flash_area_write_data_padded(&BOOTLOADER_AREA, offset, NULL, 0, 0,
|
||||
bl_len - offset),
|
||||
NULL);
|
||||
}
|
||||
|
||||
ensure(flash_lock_write(), NULL);
|
||||
|
@ -13,24 +13,10 @@ bool translations_write(const uint8_t* data, uint32_t offset, uint32_t len) {
|
||||
}
|
||||
|
||||
ensure(flash_unlock_write(), "translations_write unlock");
|
||||
for (int i = 0; i < (len / FLASH_BLOCK_SIZE); i++) {
|
||||
// todo consider alignment
|
||||
ensure(flash_area_write_block(&TRANSLATIONS_AREA,
|
||||
offset + (i * FLASH_BLOCK_SIZE),
|
||||
(const uint32_t*)&data[i * FLASH_BLOCK_SIZE]),
|
||||
"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");
|
||||
}
|
||||
// todo consider alignment
|
||||
ensure(flash_area_write_data_padded(&TRANSLATIONS_AREA, offset, data, len,
|
||||
0xFF, FLASH_ALIGN(len)),
|
||||
"translations_write write");
|
||||
ensure(flash_lock_write(), "translations_write lock");
|
||||
return true;
|
||||
}
|
||||
|
@ -28,9 +28,6 @@
|
||||
|
||||
#include "flash_ll.h"
|
||||
|
||||
#define FLASH_BURST_WORDS (4 * 8)
|
||||
#define FLASH_BURST_SIZE (FLASH_BURST_WORDS * sizeof(uint32_t))
|
||||
|
||||
void flash_init(void);
|
||||
|
||||
#endif // TREZORHAL_FLASH_H
|
||||
|
@ -194,20 +194,6 @@ secbool flash_write_word(uint16_t sector, uint32_t offset, uint32_t data) {
|
||||
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,
|
||||
const flash_block_t block) {
|
||||
return flash_write_word(sector, offset, block[0]);
|
||||
|
@ -130,22 +130,22 @@ secbool flash_sector_erase(uint16_t sector) {
|
||||
secbool flash_write_quadword(uint16_t sector, uint32_t offset,
|
||||
const uint32_t *data) {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
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))) {
|
||||
return secfalse;
|
||||
}
|
||||
}
|
||||
|
||||
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)) {
|
||||
all_match = secfalse;
|
||||
break;
|
||||
@ -160,7 +160,7 @@ secbool flash_write_quadword(uint16_t sector, uint32_t offset,
|
||||
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)) {
|
||||
return secfalse;
|
||||
}
|
||||
@ -175,7 +175,7 @@ secbool flash_write_burst(uint16_t sector, uint32_t offset,
|
||||
if (address == 0) {
|
||||
return secfalse;
|
||||
}
|
||||
if (offset % FLASH_BURST_SIZE) {
|
||||
if (offset % FLASH_BURST_SIZE) { // we write only at 128-byte boundary
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,12 @@
|
||||
|
||||
#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 {
|
||||
CLOCK_160_MHZ = 0,
|
||||
} clock_settings_t;
|
||||
|
@ -228,20 +228,6 @@ secbool flash_write_word(uint16_t sector, uint32_t offset, uint32_t data) {
|
||||
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,
|
||||
const flash_block_t block) {
|
||||
if (offset % (sizeof(uint32_t) *
|
||||
|
@ -26,9 +26,6 @@
|
||||
#include "memory.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
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
const flash_block_t block) {
|
||||
return flash_write_word(sector, offset, block[0]);
|
||||
|
@ -18,7 +18,9 @@
|
||||
*/
|
||||
|
||||
#include "flash_area.h"
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
uint32_t flash_area_get_size(const flash_area_t *area) {
|
||||
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
|
||||
|
||||
#ifdef FLASH_BURST_SIZE
|
||||
secbool flash_area_write_burst(const flash_area_t *area, uint32_t offset,
|
||||
const uint32_t *data) {
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
||||
secbool flash_area_write_block(const flash_area_t *area, uint32_t offset,
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
void (*progress)(int pos, int len)) {
|
||||
return flash_area_erase_bulk(area, 1, progress);
|
||||
|
@ -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,
|
||||
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,
|
||||
void (*progress)(int pos, int len));
|
||||
secbool __wur flash_area_erase_bulk(const flash_area_t *area, int count,
|
||||
|
Loading…
Reference in New Issue
Block a user