diff --git a/core/embed/bootloader/messages.c b/core/embed/bootloader/messages.c index 96c2f3b48b..b542e4e94b 100644 --- a/core/embed/bootloader/messages.c +++ b/core/embed/bootloader/messages.c @@ -721,12 +721,14 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, } // buffer with the received data - const uint32_t *quadword_ptr = (const uint32_t *)CHUNK_BUFFER_PTR; + const uint32_t *src = (const uint32_t *)CHUNK_BUFFER_PTR; // number of received bytes uint32_t bytes_remaining = chunk_size; // offset into the FIRMWARE_AREA part of the flash uint32_t write_offset = firmware_block * IMAGE_CHUNK_SIZE; + ensure(chunk_size % FLASH_BLOCK_SIZE == 0, NULL); + while (bytes_remaining > 0) { // erase flash before writing uint32_t bytes_erased = 0; @@ -748,12 +750,10 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, ensure(flash_unlock_write(), NULL); while (write_offset < write_end) { - // write a quad word (16 bytes) to the flash - ensure( - flash_area_write_quadword(&FIRMWARE_AREA, write_offset, quadword_ptr), - NULL); - write_offset += 4 * sizeof(uint32_t); - quadword_ptr += 4; + // write a block to the flash + ensure(flash_area_write_block(&FIRMWARE_AREA, write_offset, src), NULL); + write_offset += FLASH_BLOCK_SIZE; + src += FLASH_BLOCK_WORDS; } ensure(flash_lock_write(), NULL); diff --git a/core/embed/bootloader_ci/messages.c b/core/embed/bootloader_ci/messages.c index 3f5a92f83c..aba59ae7de 100644 --- a/core/embed/bootloader_ci/messages.c +++ b/core/embed/bootloader_ci/messages.c @@ -615,11 +615,12 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, const uint32_t *const src = (const uint32_t *const)chunk_buffer; - for (int i = 0; i < chunk_size / (sizeof(uint32_t) * 4); i++) { - ensure(flash_area_write_quadword( + ensure(chunk_size % FLASH_BLOCK_SIZE == 0, NULL); + for (int i = 0; i < chunk_size / FLASH_BLOCK_SIZE; i++) { + ensure(flash_area_write_block( &FIRMWARE_AREA, - firmware_block * IMAGE_CHUNK_SIZE + i * 4 * sizeof(uint32_t), - &src[4 * i]), + firmware_block * IMAGE_CHUNK_SIZE + i * FLASH_BLOCK_SIZE, + &src[FLASH_BLOCK_WORDS * i]), NULL); } diff --git a/core/embed/reflash/main.c b/core/embed/reflash/main.c index 5f7a3de2d8..d1f266d62e 100644 --- a/core/embed/reflash/main.c +++ b/core/embed/reflash/main.c @@ -40,6 +40,7 @@ static void flash_from_sdcard(const flash_area_t* area, uint32_t source, uint32_t length) { static uint32_t buf[SDCARD_BLOCK_SIZE / sizeof(uint32_t)]; + _Static_assert(SDCARD_BLOCK_SIZE % FLASH_BLOCK_SIZE == 0); ensure(sectrue * (source % SDCARD_BLOCK_SIZE == 0), "source not a multiple of block size"); ensure(sectrue * (length % SDCARD_BLOCK_SIZE == 0), @@ -51,10 +52,11 @@ static void flash_from_sdcard(const flash_area_t* area, uint32_t source, ensure(sdcard_read_blocks(buf, i + source / SDCARD_BLOCK_SIZE, 1), "sdcard_read_blocks"); - for (uint32_t j = 0; j < SDCARD_BLOCK_SIZE / (sizeof(uint32_t) * 4); j++) { - ensure(flash_area_write_quadword( - area, i * SDCARD_BLOCK_SIZE + j * 4 * sizeof(uint32_t), - &buf[j * 4]), + for (uint32_t j = 0; j < SDCARD_BLOCK_SIZE / FLASH_BLOCK_SIZE) + ; j++) { + ensure(flash_area_write_block( + area, i * SDCARD_BLOCK_SIZE + j * FLASH_BLOCK_SIZE, + &buf[j * FLASH_BLOCK_WORDS]), NULL); } } diff --git a/storage/flash_common.c b/storage/flash_common.c index 78fa17e07d..54e1caf371 100644 --- a/storage/flash_common.c +++ b/storage/flash_common.c @@ -1,3 +1,5 @@ +#include "flash_common.h" + #include "flash.h" secbool flash_write_byte(uint16_t sector, uint32_t offset, uint8_t data); @@ -121,16 +123,28 @@ secbool flash_area_write_word(const flash_area_t *area, uint32_t offset, return flash_write_word(sector, sector_offset, data); } -secbool flash_area_write_quadword(const flash_area_t *area, uint32_t offset, - const uint32_t *data) { - if (offset % 16 != 0) { +secbool flash_area_write_block(const flash_area_t *area, uint32_t offset, + const flash_block_t block) { + if (!FLASH_IS_ALIGNED(offset)) { return secfalse; } - for (int i = 0; i < 4; i++) { - if (sectrue != - flash_area_write_word(area, offset + i * sizeof(uint32_t), data[i])) { + + uint16_t sector; + uint32_t sector_offset; + if (sectrue != get_sector_and_offset(area, offset, §or, §or_offset)) { + return secfalse; + } + +#if FLASH_BLOCK_WORDS == 1 + return flash_write_word(sector, sector_offset, block); +#else + for (int i = 0; i < FLASH_BLOCK_WORDS; i++) { + if (sectrue != flash_write_word(sector, + sector_offset + i * sizeof(uint32_t), + block[i])) { return secfalse; } } return sectrue; +#endif } diff --git a/storage/flash_common.h b/storage/flash_common.h index b8cac2b55f..0d38752d85 100644 --- a/storage/flash_common.h +++ b/storage/flash_common.h @@ -14,6 +14,14 @@ typedef struct { uint8_t num_subareas; } flash_area_t; +#define FLASH_BLOCK_SIZE (sizeof(uint32_t) * FLASH_BLOCK_WORDS) + +#if FLASH_BLOCK_WORDS == 1 +typedef uint32_t flash_block_t; +#else +typedef uint32_t flash_block_t[FLASH_BLOCK_WORDS]; +#endif + void flash_init(void); secbool __wur flash_unlock_write(void); @@ -39,7 +47,7 @@ secbool __wur flash_area_write_byte(const flash_area_t *area, uint32_t offset, secbool __wur flash_area_write_word(const flash_area_t *area, uint32_t offset, uint32_t data); #endif -secbool __wur flash_area_write_quadword(const flash_area_t *area, - uint32_t offset, const uint32_t *data); +secbool __wur flash_area_write_block(const flash_area_t *area, uint32_t offset, + const flash_block_t block); #endif