From 238e3fd7c1491b93c403262ee6385877c0dbd329 Mon Sep 17 00:00:00 2001 From: tychovrahe Date: Fri, 30 Jun 2023 12:12:55 +0200 Subject: [PATCH] refactor(core): add abstraction over flash memory layout [no changelog] --- core/SConscript.boardloader | 3 + core/SConscript.bootloader | 3 + core/SConscript.bootloader_ci | 3 + core/SConscript.bootloader_emu | 4 +- core/SConscript.firmware | 2 + core/SConscript.prodtest | 3 + core/SConscript.reflash | 3 + core/SConscript.unix | 18 +++ core/embed/boardloader/main.c | 47 ++----- core/embed/bootloader/emulator.c | 20 +-- core/embed/bootloader/main.c | 44 +++--- core/embed/bootloader/messages.c | 46 ++----- core/embed/bootloader_ci/main.c | 8 +- core/embed/bootloader_ci/messages.c | 50 +++---- .../extmod/modtrezorconfig/norcow_config.h | 4 +- .../extmod/modtrezorutils/modtrezorutils.c | 15 ++- core/embed/firmware/bl_check.c | 14 +- core/embed/firmware/main.c | 2 + core/embed/{trezorhal/stm32f4 => lib}/image.c | 27 ++-- core/embed/{trezorhal => lib}/image.h | 11 +- core/embed/lib/unit_variant.c | 1 + core/embed/models/layout_common.h | 22 +++ core/embed/models/model.h | 2 + core/embed/models/model_D001.h | 7 + core/embed/models/model_D001_layout.c | 1 + core/embed/models/model_T1B1.h | 6 + core/embed/models/model_T1B1_layout.c | 39 ++++++ core/embed/models/model_T2B1.h | 7 + core/embed/models/model_T2B1_layout.c | 1 + core/embed/models/model_T2T1.h | 7 + core/embed/models/model_T2T1_layout.c | 82 +++++++++++ core/embed/prodtest/main.c | 7 +- core/embed/reflash/main.c | 28 ++-- core/embed/trezorhal/flash.h | 118 ++++------------ core/embed/trezorhal/stm32f4/common.c | 2 + core/embed/trezorhal/stm32f4/flash.c | 114 +++++++++------- core/embed/trezorhal/stm32f4/lowlevel.c | 9 -- core/embed/trezorhal/stm32f4/platform.h | 2 + core/embed/trezorhal/unix/flash.c | 84 ++++++------ core/embed/trezorhal/unix/image.c | 1 - core/embed/trezorhal/unix/platform.h | 2 + core/embed/trezorhal/unix/touch/touch.c | 1 + core/site_scons/boards/discovery.py | 3 + core/site_scons/boards/stm32f4_common.py | 1 - core/site_scons/boards/trezor_1.py | 3 + core/site_scons/boards/trezor_r_v10.py | 3 + core/site_scons/boards/trezor_r_v3.py | 3 + core/site_scons/boards/trezor_r_v4.py | 3 + core/site_scons/boards/trezor_r_v6.py | 3 + core/site_scons/boards/trezor_t.py | 3 + legacy/Makefile | 1 + legacy/flash.c | 81 ++++++++--- legacy/flash.h | 9 +- legacy/norcow_config.h | 2 + storage/flash_common.c | 127 ++++++++++++++++++ storage/flash_common.h | 46 +++++++ storage/norcow.c | 44 +++--- storage/tests/c/Makefile | 2 + storage/tests/c/flash.c | 62 ++++++--- storage/tests/c/flash.h | 18 +-- storage/tests/c/norcow_config.h | 2 - storage/tests/c/test_layout.c | 21 +++ storage/tests/c/test_layout.h | 10 ++ 63 files changed, 872 insertions(+), 445 deletions(-) rename core/embed/{trezorhal/stm32f4 => lib}/image.c (94%) rename core/embed/{trezorhal => lib}/image.h (89%) create mode 100644 core/embed/models/layout_common.h create mode 120000 core/embed/models/model_D001_layout.c create mode 100644 core/embed/models/model_T1B1_layout.c create mode 120000 core/embed/models/model_T2B1_layout.c create mode 100644 core/embed/models/model_T2T1_layout.c delete mode 120000 core/embed/trezorhal/unix/image.c create mode 100644 storage/flash_common.c create mode 100644 storage/flash_common.h create mode 100644 storage/tests/c/test_layout.c create mode 100644 storage/tests/c/test_layout.h diff --git a/core/SConscript.boardloader b/core/SConscript.boardloader index 050d23cdf..2e2e69c7e 100644 --- a/core/SConscript.boardloader +++ b/core/SConscript.boardloader @@ -32,6 +32,7 @@ PATH_HAL = [] CCFLAGS_MOD += '-Wno-sequence-point ' CPPPATH_MOD += [ 'vendor/trezor-crypto', + 'vendor/trezor-storage', ] CPPDEFINES_MOD += [ 'AES_128', @@ -60,7 +61,9 @@ SOURCE_MOD += [ 'embed/lib/colors.c', 'embed/lib/fonts/fonts.c', 'embed/lib/fonts/font_bitmap.c', + 'embed/lib/image.c', 'embed/lib/mini_printf.c', + 'vendor/trezor-storage/flash_common.c', ] SOURCE_BOARDLOADER = [ diff --git a/core/SConscript.bootloader b/core/SConscript.bootloader index b4b68cace..0eaf184e6 100644 --- a/core/SConscript.bootloader +++ b/core/SConscript.bootloader @@ -47,6 +47,7 @@ elif TREZOR_MODEL in ('T', 'DISC1'): CCFLAGS_MOD += '-Wno-sequence-point ' CPPPATH_MOD += [ 'vendor/trezor-crypto', + 'vendor/trezor-storage', ] CPPDEFINES_MOD += [ 'AES_128', @@ -85,10 +86,12 @@ SOURCE_MOD += [ 'embed/lib/display.c', 'embed/lib/fonts/fonts.c', 'embed/lib/fonts/font_bitmap.c', + 'embed/lib/image.c', 'embed/extmod/modtrezorcrypto/rand.c', 'vendor/micropython/lib/uzlib/adler32.c', 'vendor/micropython/lib/uzlib/crc32.c', 'vendor/micropython/lib/uzlib/tinflate.c', + 'vendor/trezor-storage/flash_common.c', ] SOURCE_NANOPB = [ diff --git a/core/SConscript.bootloader_ci b/core/SConscript.bootloader_ci index 30df7ae0d..181f91402 100644 --- a/core/SConscript.bootloader_ci +++ b/core/SConscript.bootloader_ci @@ -45,6 +45,7 @@ elif TREZOR_MODEL in ('T', ): CCFLAGS_MOD += '-Wno-sequence-point ' CPPPATH_MOD += [ 'vendor/trezor-crypto', + 'vendor/trezor-storage', ] CPPDEFINES_MOD += [ 'AES_128', @@ -65,6 +66,7 @@ SOURCE_MOD += [ 'vendor/trezor-crypto/memzero.c', 'vendor/trezor-crypto/rand.c', 'vendor/trezor-crypto/sha2.c', + 'vendor/trezor-storage/flash_common.c', ] # modtrezorui @@ -76,6 +78,7 @@ SOURCE_MOD += [ 'embed/lib/colors.c', 'embed/lib/fonts/fonts.c', 'embed/lib/fonts/font_bitmap.c', + 'embed/lib/image.c', 'embed/lib/mini_printf.c', 'embed/extmod/modtrezorcrypto/rand.c', 'vendor/micropython/lib/uzlib/adler32.c', diff --git a/core/SConscript.bootloader_emu b/core/SConscript.bootloader_emu index a9dc34b53..0f8ea3eb8 100644 --- a/core/SConscript.bootloader_emu +++ b/core/SConscript.bootloader_emu @@ -44,6 +44,7 @@ elif TREZOR_MODEL in ('T', ): CCFLAGS_MOD += '-Wno-sequence-point ' CPPPATH_MOD += [ 'vendor/trezor-crypto', + 'vendor/trezor-storage', ] CPPDEFINES_MOD += [ 'AES_128', @@ -82,11 +83,13 @@ SOURCE_MOD += [ 'embed/lib/display.c', 'embed/lib/fonts/fonts.c', 'embed/lib/fonts/font_bitmap.c', + 'embed/lib/image.c', 'embed/lib/touch.c', 'embed/extmod/modtrezorcrypto/rand.c', 'vendor/micropython/lib/uzlib/adler32.c', 'vendor/micropython/lib/uzlib/crc32.c', 'vendor/micropython/lib/uzlib/tinflate.c', + 'vendor/trezor-storage/flash_common.c', ] SOURCE_NANOPB = [ @@ -104,7 +107,6 @@ SOURCE_BOOTLOADER = [ ] SOURCE_TREZORHAL = [ - 'embed/trezorhal/unix/image.c', 'embed/trezorhal/unix/display-unix.c', 'embed/trezorhal/unix/flash.c', 'embed/trezorhal/unix/common.c', diff --git a/core/SConscript.firmware b/core/SConscript.firmware index f2ced018d..88c33207e 100644 --- a/core/SConscript.firmware +++ b/core/SConscript.firmware @@ -53,6 +53,7 @@ SOURCE_MOD += [ 'embed/extmod/modtrezorconfig/modtrezorconfig.c', 'vendor/trezor-storage/norcow.c', 'vendor/trezor-storage/storage.c', + 'vendor/trezor-storage/flash_common.c', ] # modtrezorcrypto @@ -184,6 +185,7 @@ SOURCE_MOD += [ 'embed/lib/display.c', 'embed/lib/fonts/fonts.c', 'embed/lib/fonts/font_bitmap.c', + 'embed/lib/image.c', 'embed/extmod/modtrezorui/modtrezorui.c', 'vendor/micropython/lib/uzlib/adler32.c', 'vendor/micropython/lib/uzlib/crc32.c', diff --git a/core/SConscript.prodtest b/core/SConscript.prodtest index 008219898..a1be842ae 100644 --- a/core/SConscript.prodtest +++ b/core/SConscript.prodtest @@ -45,6 +45,7 @@ elif TREZOR_MODEL in ('T', ): # modtrezorcrypto CPPPATH_MOD += [ 'vendor/trezor-crypto', + 'vendor/trezor-storage', ] SOURCE_MOD += [ 'vendor/trezor-crypto/chacha_drbg.c', @@ -64,11 +65,13 @@ SOURCE_MOD += [ 'embed/lib/colors.c', 'embed/lib/fonts/fonts.c', 'embed/lib/fonts/font_bitmap.c', + 'embed/lib/image.c', 'embed/lib/mini_printf.c', 'embed/lib/qr-code-generator/qrcodegen.c', 'vendor/micropython/lib/uzlib/adler32.c', 'vendor/micropython/lib/uzlib/crc32.c', 'vendor/micropython/lib/uzlib/tinflate.c', + 'vendor/trezor-storage/flash_common.c', ] SOURCE_PRODTEST = [ diff --git a/core/SConscript.reflash b/core/SConscript.reflash index 804d448f5..ea2cb2a1f 100644 --- a/core/SConscript.reflash +++ b/core/SConscript.reflash @@ -43,6 +43,7 @@ elif TREZOR_MODEL in ('T', ): # modtrezorcrypto CPPPATH_MOD += [ 'vendor/trezor-crypto', + 'vendor/trezor-storage', ] SOURCE_MOD += [ 'vendor/trezor-crypto/memzero.c', @@ -57,10 +58,12 @@ SOURCE_MOD += [ 'embed/lib/colors.c', 'embed/lib/fonts/fonts.c', 'embed/lib/fonts/font_bitmap.c', + 'embed/lib/image.c', 'embed/lib/mini_printf.c', 'vendor/micropython/lib/uzlib/adler32.c', 'vendor/micropython/lib/uzlib/crc32.c', 'vendor/micropython/lib/uzlib/tinflate.c', + 'vendor/trezor-storage/flash_common.c', ] SOURCE_REFLASH = [ diff --git a/core/SConscript.unix b/core/SConscript.unix index aa2091916..2ec3ef33a 100644 --- a/core/SConscript.unix +++ b/core/SConscript.unix @@ -58,6 +58,7 @@ SOURCE_MOD += [ 'embed/extmod/modtrezorconfig/modtrezorconfig.c', 'vendor/trezor-storage/norcow.c', 'vendor/trezor-storage/storage.c', + 'vendor/trezor-storage/flash_common.c', ] # modtrezorcrypto @@ -190,11 +191,28 @@ SOURCE_MOD += [ 'embed/lib/display.c', 'embed/lib/fonts/fonts.c', 'embed/lib/fonts/font_bitmap.c', + 'embed/lib/image.c', 'embed/extmod/modtrezorui/modtrezorui.c', 'vendor/micropython/lib/uzlib/adler32.c', 'vendor/micropython/lib/uzlib/crc32.c', 'vendor/micropython/lib/uzlib/tinflate.c', ] + +if TREZOR_MODEL in ('1', ): + SOURCE_MOD += [ + 'embed/models/model_T1B1_layout.c', + ] +elif TREZOR_MODEL in ('T', ): + SOURCE_MOD += [ + 'embed/models/model_T2T1_layout.c', + ] +elif TREZOR_MODEL in ('R', ): + SOURCE_MOD += [ + 'embed/models/model_T2B1_layout.c', + ] + + + CPPDEFINES_MOD += [ 'TREZOR_UI2', ] diff --git a/core/embed/boardloader/main.c b/core/embed/boardloader/main.c index 7fc5f7a35..c4599544c 100644 --- a/core/embed/boardloader/main.c +++ b/core/embed/boardloader/main.c @@ -19,12 +19,14 @@ #include +#include TREZOR_BOARD #include "board_capabilities.h" #include "common.h" #include "compiler_traits.h" #include "display.h" #include "flash.h" #include "image.h" +#include "model.h" #include "rng.h" #ifdef USE_SD_CARD #include "sdcard.h" @@ -141,31 +143,7 @@ static secbool copy_sdcard(void) { display_printf("\n\nerasing flash:\n\n"); // erase all flash (except boardloader) - static const uint8_t sectors[] = { - FLASH_SECTOR_STORAGE_1, - FLASH_SECTOR_STORAGE_2, - 3, - FLASH_SECTOR_BOOTLOADER, - FLASH_SECTOR_FIRMWARE_START, - 7, - 8, - 9, - 10, - FLASH_SECTOR_FIRMWARE_END, - FLASH_SECTOR_UNUSED_START, - 13, - 14, - FLASH_SECTOR_UNUSED_END, - FLASH_SECTOR_FIRMWARE_EXTRA_START, - 18, - 19, - 20, - 21, - 22, - FLASH_SECTOR_FIRMWARE_EXTRA_END, - }; - if (sectrue != - flash_erase_sectors(sectors, sizeof(sectors), progress_callback)) { + if (sectrue != flash_area_erase(&ALL_WIPE_AREA, progress_callback)) { display_printf(" failed\n"); return secfalse; } @@ -183,9 +161,9 @@ static secbool copy_sdcard(void) { for (int i = 0; i < (IMAGE_HEADER_SIZE + codelen) / SDCARD_BLOCK_SIZE; i++) { ensure(sdcard_read_blocks(sdcard_buf, i, 1), NULL); for (int j = 0; j < SDCARD_BLOCK_SIZE / sizeof(uint32_t); j++) { - ensure(flash_write_word(FLASH_SECTOR_BOOTLOADER, - i * SDCARD_BLOCK_SIZE + j * sizeof(uint32_t), - sdcard_buf[j]), + ensure(flash_area_write_word(&BOOTLOADER_AREA, + i * SDCARD_BLOCK_SIZE + j * sizeof(uint32_t), + sdcard_buf[j]), NULL); } } @@ -210,7 +188,7 @@ int main(void) { if (sectrue != flash_configure_option_bytes()) { // display is not initialized so don't call ensure const secbool r = - flash_erase_sectors(STORAGE_SECTORS, STORAGE_SECTORS_COUNT, NULL); + flash_area_erase_bulk(STORAGE_AREAS, STORAGE_AREAS_COUNT, NULL); (void)r; return 2; } @@ -232,9 +210,9 @@ int main(void) { } #endif - const image_header *hdr = - read_image_header((const uint8_t *)BOOTLOADER_START, - BOOTLOADER_IMAGE_MAGIC, BOOTLOADER_IMAGE_MAXSIZE); + const image_header *hdr = read_image_header( + (const uint8_t *)BOOTLOADER_START, BOOTLOADER_IMAGE_MAGIC, + flash_area_get_size(&BOOTLOADER_AREA)); ensure(hdr == (const image_header *)BOOTLOADER_START ? sectrue : secfalse, "invalid bootloader header"); @@ -243,10 +221,7 @@ int main(void) { BOARDLOADER_KEYS), "invalid bootloader signature"); - const uint8_t sectors[] = { - FLASH_SECTOR_BOOTLOADER, - }; - ensure(check_image_contents(hdr, IMAGE_HEADER_SIZE, sectors, 1), + ensure(check_image_contents(hdr, IMAGE_HEADER_SIZE, &BOOTLOADER_AREA), "invalid bootloader hash"); ensure_compatible_settings(); diff --git a/core/embed/bootloader/emulator.c b/core/embed/bootloader/emulator.c index 936c4e286..68c8f5ab0 100644 --- a/core/embed/bootloader/emulator.c +++ b/core/embed/bootloader/emulator.c @@ -4,10 +4,14 @@ #include "bootui.h" #include "common.h" #include "display.h" -#include "emulator.h" #include "flash.h" +#include "model.h" #include "rust_ui.h" +#include "emulator.h" + +#undef FIRMWARE_START + uint8_t *FIRMWARE_START = 0; uint32_t stay_in_bootloader_flag; @@ -15,7 +19,7 @@ void set_core_clock(int) {} int bootloader_main(void); -bool sector_is_empty(uint8_t sector) { +bool sector_is_empty(uint16_t sector) { const uint8_t *storage = flash_get_address(sector, 0, 0); size_t storage_size = flash_sector_size(sector); for (size_t i = 0; i < storage_size; i++) { @@ -28,12 +32,11 @@ bool sector_is_empty(uint8_t sector) { __attribute__((noreturn)) int main(int argc, char **argv) { flash_init(); - FIRMWARE_START = - (uint8_t *)flash_get_address(FLASH_SECTOR_FIRMWARE_START, 0, 0); + FIRMWARE_START = (uint8_t *)flash_area_get_address(&FIRMWARE_AREA, 0, 0); // simulate non-empty storage so that we know whether it was erased or not - if (sector_is_empty(FLASH_SECTOR_STORAGE_1)) { - secbool ret = flash_write_word(FLASH_SECTOR_STORAGE_1, 16, 0x12345678); + if (sector_is_empty(STORAGE_AREAS[0].subarea[0].first_sector)) { + secbool ret = flash_area_write_word(&STORAGE_AREAS[0], 16, 0x12345678); (void)ret; } @@ -63,8 +66,9 @@ void mpu_config_bootloader(void) {} void mpu_config_off(void) {} __attribute__((noreturn)) void jump_to(void *addr) { - bool storage_is_erased = sector_is_empty(FLASH_SECTOR_STORAGE_1) && - sector_is_empty(FLASH_SECTOR_STORAGE_2); + bool storage_is_erased = + sector_is_empty(STORAGE_AREAS[0].subarea[0].first_sector) && + sector_is_empty(STORAGE_AREAS[1].subarea[0].first_sector); if (storage_is_erased) { printf("STORAGE WAS ERASED\n"); diff --git a/core/embed/bootloader/main.c b/core/embed/bootloader/main.c index 46940dbe8..a33c67b78 100644 --- a/core/embed/bootloader/main.c +++ b/core/embed/bootloader/main.c @@ -26,14 +26,7 @@ #include "image.h" #include "random_delays.h" #include "secbool.h" -#ifdef TREZOR_EMULATOR -#include "emulator.h" -#else -#include "compiler_traits.h" -#include "mini_printf.h" -#include "mpu.h" -#include "platform.h" -#endif + #ifdef USE_DMA2D #include "dma2d.h" #endif @@ -61,6 +54,15 @@ #include "rust_ui.h" #include "unit_variant.h" +#ifdef TREZOR_EMULATOR +#include "emulator.h" +#else +#include "compiler_traits.h" +#include "mini_printf.h" +#include "mpu.h" +#include "platform.h" +#endif + const uint8_t BOOTLOADER_KEY_M = 2; const uint8_t BOOTLOADER_KEY_N = 3; static const uint8_t * const BOOTLOADER_KEYS[] = { @@ -305,9 +307,10 @@ int bootloader_main(void) { } if (sectrue == firmware_present) { - hdr = read_image_header((const uint8_t *)(FIRMWARE_START + vhdr.hdrlen), - FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE); - if (hdr != (const image_header *)(FIRMWARE_START + vhdr.hdrlen)) { + hdr = read_image_header( + (const uint8_t *)(size_t)(FIRMWARE_START + vhdr.hdrlen), + FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE); + if (hdr != (const image_header *)(size_t)(FIRMWARE_START + vhdr.hdrlen)) { firmware_present = secfalse; } } @@ -319,9 +322,8 @@ int bootloader_main(void) { check_image_header_sig(hdr, vhdr.vsig_m, vhdr.vsig_n, vhdr.vpub); } if (sectrue == firmware_present) { - firmware_present = - check_image_contents(hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen, - FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT); + firmware_present = check_image_contents( + hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen, &FIRMWARE_AREA); } #if defined TREZOR_MODEL_T @@ -408,7 +410,7 @@ int bootloader_main(void) { ui_screen_welcome(); // erase storage - ensure(flash_erase_sectors(STORAGE_SECTORS, STORAGE_SECTORS_COUNT, NULL), + ensure(flash_area_erase_bulk(STORAGE_AREAS, STORAGE_AREAS_COUNT, NULL), NULL); // and start the usb loop @@ -502,11 +504,13 @@ int bootloader_main(void) { ensure(check_vendor_header_lock(&vhdr), "Unauthorized vendor keys"); - hdr = read_image_header((const uint8_t *)(FIRMWARE_START + vhdr.hdrlen), - FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE); + hdr = + read_image_header((const uint8_t *)(size_t)(FIRMWARE_START + vhdr.hdrlen), + FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE); - ensure(hdr == (const image_header *)(FIRMWARE_START + vhdr.hdrlen) ? sectrue - : secfalse, + ensure(hdr == (const image_header *)(size_t)(FIRMWARE_START + vhdr.hdrlen) + ? sectrue + : secfalse, "Firmware is corrupted"); ensure(check_image_model(hdr), "Wrong firmware model"); @@ -515,7 +519,7 @@ int bootloader_main(void) { "Firmware is corrupted"); ensure(check_image_contents(hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen, - FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT), + &FIRMWARE_AREA), "Firmware is corrupted"); // if all VTRUST flags are unset = ultimate trust => skip the procedure diff --git a/core/embed/bootloader/messages.c b/core/embed/bootloader/messages.c index 488861a98..94d229bcc 100644 --- a/core/embed/bootloader/messages.c +++ b/core/embed/bootloader/messages.c @@ -352,7 +352,7 @@ void process_msg_FirmwareErase(uint8_t iface_num, uint32_t msg_size, firmware_remaining = msg_recv.has_length ? msg_recv.length : 0; if ((firmware_remaining > 0) && ((firmware_remaining % sizeof(uint32_t)) == 0) && - (firmware_remaining <= (FIRMWARE_SECTORS_COUNT * IMAGE_CHUNK_SIZE))) { + (firmware_remaining <= FIRMWARE_IMAGE_MAXSIZE)) { // request new firmware chunk_requested = (firmware_remaining > IMAGE_INIT_CHUNK_SIZE) ? IMAGE_INIT_CHUNK_SIZE @@ -591,12 +591,10 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, // if firmware is not upgrade, erase storage if (sectrue != should_keep_seed) { - ensure( - flash_erase_sectors(STORAGE_SECTORS, STORAGE_SECTORS_COUNT, NULL), - NULL); + ensure(flash_area_erase_bulk(STORAGE_AREAS, STORAGE_AREAS_COUNT, NULL), + NULL); } - ensure(flash_erase_sectors(FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT, - ui_screen_install_progress_erase), + ensure(flash_area_erase(&FIRMWARE_AREA, ui_screen_install_progress_erase), NULL); headers_offset = IMAGE_HEADER_SIZE + vhdr.hdrlen; @@ -621,7 +619,8 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, } // should not happen, but double-check - if (firmware_block >= FIRMWARE_SECTORS_COUNT) { + if (flash_area_get_address(&FIRMWARE_AREA, firmware_block * IMAGE_CHUNK_SIZE, + 0) == NULL) { MSG_SEND_INIT(Failure); MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError); MSG_SEND_ASSIGN_STRING(message, "Firmware too big"); @@ -651,9 +650,12 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, ensure(flash_unlock_write(), NULL); const uint32_t *const src = (const uint32_t *const)CHUNK_BUFFER_PTR; - for (int i = 0; i < chunk_size / sizeof(uint32_t); i++) { - ensure(flash_write_word(FIRMWARE_SECTORS[firmware_block], - i * sizeof(uint32_t), src[i]), + + for (int i = 0; i < chunk_size / (sizeof(uint32_t) * 4); i++) { + ensure(flash_area_write_quadword( + &FIRMWARE_AREA, + firmware_block * IMAGE_CHUNK_SIZE + i * 4 * sizeof(uint32_t), + &src[4 * i]), NULL); } @@ -680,29 +682,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, } secbool bootloader_WipeDevice(void) { - static const uint8_t sectors[] = { - FLASH_SECTOR_STORAGE_1, - FLASH_SECTOR_STORAGE_2, - // 3, // skip because of MPU protection - FLASH_SECTOR_FIRMWARE_START, - 7, - 8, - 9, - 10, - FLASH_SECTOR_FIRMWARE_END, - FLASH_SECTOR_UNUSED_START, - 13, - 14, - // FLASH_SECTOR_UNUSED_END, // skip because of MPU protection - FLASH_SECTOR_FIRMWARE_EXTRA_START, - 18, - 19, - 20, - 21, - 22, - FLASH_SECTOR_FIRMWARE_EXTRA_END, - }; - return flash_erase_sectors(sectors, sizeof(sectors), ui_screen_wipe_progress); + return flash_area_erase(&WIPE_AREA, ui_screen_wipe_progress); } int process_msg_WipeDevice(uint8_t iface_num, uint32_t msg_size, uint8_t *buf) { diff --git a/core/embed/bootloader_ci/main.c b/core/embed/bootloader_ci/main.c index 901d2b494..3810d6864 100644 --- a/core/embed/bootloader_ci/main.c +++ b/core/embed/bootloader_ci/main.c @@ -37,6 +37,7 @@ #include "bootui.h" #include "messages.h" +#include "model.h" // #include "mpu.h" const uint8_t BOOTLOADER_KEY_M = 2; @@ -262,9 +263,8 @@ int main(void) { check_image_header_sig(hdr, vhdr.vsig_m, vhdr.vsig_n, vhdr.vpub); } if (sectrue == firmware_present) { - firmware_present = - check_image_contents(hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen, - FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT); + firmware_present = check_image_contents( + hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen, &FIRMWARE_AREA); } // always start bootloader even if firmware is already present @@ -299,7 +299,7 @@ int main(void) { "invalid firmware signature"); ensure(check_image_contents(hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen, - FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT), + &FIRMWARE_AREA), "invalid firmware hash"); // do not check any trust flags on header, proceed diff --git a/core/embed/bootloader_ci/messages.c b/core/embed/bootloader_ci/messages.c index c27b8363d..4695fb848 100644 --- a/core/embed/bootloader_ci/messages.c +++ b/core/embed/bootloader_ci/messages.c @@ -27,6 +27,7 @@ #include "common.h" #include "flash.h" #include "image.h" +#include "model.h" #include "secbool.h" #include "usb.h" #include "version.h" @@ -339,7 +340,7 @@ void process_msg_FirmwareErase(uint8_t iface_num, uint32_t msg_size, firmware_remaining = msg_recv.has_length ? msg_recv.length : 0; if ((firmware_remaining > 0) && ((firmware_remaining % sizeof(uint32_t)) == 0) && - (firmware_remaining <= (FIRMWARE_SECTORS_COUNT * IMAGE_CHUNK_SIZE))) { + (firmware_remaining <= (FIRMWARE_IMAGE_MAXSIZE))) { // request new firmware chunk_requested = (firmware_remaining > IMAGE_INIT_CHUNK_SIZE) ? IMAGE_INIT_CHUNK_SIZE @@ -578,14 +579,14 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, ui_screen_install_start(); ui_fadein(); - ensure(flash_erase_sectors(FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT, - ui_screen_install_progress_erase), + ensure(flash_area_erase(&FIRMWARE_AREA, ui_screen_install_progress_erase), NULL); } } // should not happen, but double-check - if (firmware_block >= FIRMWARE_SECTORS_COUNT) { + if (flash_area_get_address(&FIRMWARE_AREA, firmware_block * IMAGE_CHUNK_SIZE, + 0) == NULL) { MSG_SEND_INIT(Failure); MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError); MSG_SEND_ASSIGN_STRING(message, "Firmware too big"); @@ -615,9 +616,12 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, ensure(flash_unlock_write(), NULL); const uint32_t *const src = (const uint32_t *const)chunk_buffer; - for (int i = 0; i < chunk_size / sizeof(uint32_t); i++) { - ensure(flash_write_word(FIRMWARE_SECTORS[firmware_block], - i * sizeof(uint32_t), src[i]), + + for (int i = 0; i < chunk_size / (sizeof(uint32_t) * 4); i++) { + ensure(flash_area_write_quadword( + &FIRMWARE_AREA, + firmware_block * IMAGE_CHUNK_SIZE + i * 4 * sizeof(uint32_t), + &src[4 * i]), NULL); } @@ -644,30 +648,14 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, } int process_msg_WipeDevice(uint8_t iface_num, uint32_t msg_size, uint8_t *buf) { - static const uint8_t sectors[] = { - FLASH_SECTOR_STORAGE_1, - FLASH_SECTOR_STORAGE_2, - // 3, // skip because of MPU protection - FLASH_SECTOR_FIRMWARE_START, - 7, - 8, - 9, - 10, - FLASH_SECTOR_FIRMWARE_END, - FLASH_SECTOR_UNUSED_START, - 13, - 14, - // FLASH_SECTOR_UNUSED_END, // skip because of MPU protection - FLASH_SECTOR_FIRMWARE_EXTRA_START, - 18, - 19, - 20, - 21, - 22, - FLASH_SECTOR_FIRMWARE_EXTRA_END, - }; - if (sectrue != - flash_erase_sectors(sectors, sizeof(sectors), ui_screen_wipe_progress)) { + flash_area_t wipe_area[STORAGE_AREAS_COUNT + 1]; + for (int i = 0; i < STORAGE_AREAS_COUNT; i++) { + memcpy(&wipe_area[i], &STORAGE_AREAS[i], sizeof(flash_area_t)); + } + memcpy(&wipe_area[STORAGE_AREAS_COUNT], &FIRMWARE_AREA, sizeof(flash_area_t)); + + if (sectrue != flash_area_erase_bulk(wipe_area, STORAGE_AREAS_COUNT + 1, + ui_screen_wipe_progress)) { MSG_SEND_INIT(Failure); MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError); MSG_SEND_ASSIGN_STRING(message, "Could not erase flash"); diff --git a/core/embed/extmod/modtrezorconfig/norcow_config.h b/core/embed/extmod/modtrezorconfig/norcow_config.h index f20237afe..7b43fa41b 100644 --- a/core/embed/extmod/modtrezorconfig/norcow_config.h +++ b/core/embed/extmod/modtrezorconfig/norcow_config.h @@ -21,6 +21,7 @@ #define __NORCOW_CONFIG_H__ #include "flash.h" +#include "model.h" #define NORCOW_HEADER_LEN 0 #define NORCOW_SECTOR_COUNT 2 @@ -34,9 +35,6 @@ #error Unknown Trezor model #endif -#define NORCOW_SECTORS \ - { FLASH_SECTOR_STORAGE_1, FLASH_SECTOR_STORAGE_2 } - /* * Current storage version. */ diff --git a/core/embed/extmod/modtrezorutils/modtrezorutils.c b/core/embed/extmod/modtrezorutils/modtrezorutils.c index 1d9474fbc..10820f5a2 100644 --- a/core/embed/extmod/modtrezorutils/modtrezorutils.c +++ b/core/embed/extmod/modtrezorutils/modtrezorutils.c @@ -167,16 +167,18 @@ STATIC mp_obj_t mod_trezorutils_firmware_hash(size_t n_args, ui_wait_callback = args[1]; } - ui_progress(ui_wait_callback, 0, FIRMWARE_SECTORS_COUNT); - for (int i = 0; i < FIRMWARE_SECTORS_COUNT; i++) { - uint8_t sector = FIRMWARE_SECTORS[i]; + uint16_t firmware_sectors = flash_total_sectors(&FIRMWARE_AREA); + + ui_progress(ui_wait_callback, 0, firmware_sectors); + for (int i = 0; i < firmware_sectors; i++) { + uint8_t sector = flash_get_sector_num(&FIRMWARE_AREA, i); uint32_t size = flash_sector_size(sector); const void *data = flash_get_address(sector, 0, size); if (data == NULL) { mp_raise_msg(&mp_type_RuntimeError, "Failed to read firmware."); } blake2s_Update(&ctx, data, size); - ui_progress(ui_wait_callback, i + 1, FIRMWARE_SECTORS_COUNT); + ui_progress(ui_wait_callback, i + 1, firmware_sectors); } vstr_t vstr = {0}; @@ -200,8 +202,9 @@ STATIC mp_obj_t mod_trezorutils_firmware_vendor(void) { return mp_obj_new_str_copy(&mp_type_str, (const uint8_t *)"EMULATOR", 8); #else vendor_header vhdr = {0}; - uint32_t size = flash_sector_size(FLASH_SECTOR_FIRMWARE_START); - const void *data = flash_get_address(FLASH_SECTOR_FIRMWARE_START, 0, size); + uint32_t size = flash_sector_size(FIRMWARE_AREA.subarea[0].first_sector); + const void *data = + flash_get_address(FIRMWARE_AREA.subarea[0].first_sector, 0, size); if (data == NULL || sectrue != read_vendor_header(data, &vhdr)) { mp_raise_msg(&mp_type_RuntimeError, "Failed to read vendor header."); } diff --git a/core/embed/firmware/bl_check.c b/core/embed/firmware/bl_check.c index cb44a0b8e..3c527806a 100644 --- a/core/embed/firmware/bl_check.c +++ b/core/embed/firmware/bl_check.c @@ -113,7 +113,7 @@ void check_and_replace_bootloader(void) { // compute current bootloader hash uint8_t hash[BLAKE2S_DIGEST_LENGTH]; const uint32_t bl_len = 128 * 1024; - const void *bl_data = flash_get_address(FLASH_SECTOR_BOOTLOADER, 0, bl_len); + const void *bl_data = flash_area_get_address(&BOOTLOADER_AREA, 0, bl_len); blake2s(bl_data, bl_len, hash, BLAKE2S_DIGEST_LENGTH); // don't whitelist the valid bootloaders for now @@ -172,16 +172,16 @@ void check_and_replace_bootloader(void) { ensure(secfalse, "Incompatible embedded bootloader"); } - ensure(flash_erase(FLASH_SECTOR_BOOTLOADER), NULL); + ensure(flash_area_erase(&BOOTLOADER_AREA, NULL), NULL); ensure(flash_unlock_write(), NULL); for (int i = 0; i < len / sizeof(uint32_t); i++) { - ensure(flash_write_word(FLASH_SECTOR_BOOTLOADER, i * sizeof(uint32_t), - data[i]), - NULL); + ensure( + flash_area_write_word(&BOOTLOADER_AREA, i * sizeof(uint32_t), data[i]), + NULL); } for (int i = len / sizeof(uint32_t); i < 128 * 1024 / sizeof(uint32_t); i++) { - ensure(flash_write_word(FLASH_SECTOR_BOOTLOADER, i * sizeof(uint32_t), - 0x00000000), + ensure(flash_area_write_word(&BOOTLOADER_AREA, i * sizeof(uint32_t), + 0x00000000), NULL); } ensure(flash_lock_write(), NULL); diff --git a/core/embed/firmware/main.c b/core/embed/firmware/main.c index e2a50b036..de0d3eb3e 100644 --- a/core/embed/firmware/main.c +++ b/core/embed/firmware/main.c @@ -43,8 +43,10 @@ #include "display.h" #include "flash.h" #include "image.h" +#include "model.h" #include "mpu.h" #include "random_delays.h" + #ifdef USE_RGB_LED #include "rgb_led.h" #endif diff --git a/core/embed/trezorhal/stm32f4/image.c b/core/embed/lib/image.c similarity index 94% rename from core/embed/trezorhal/stm32f4/image.c rename to core/embed/lib/image.c index 6c6c043ed..424b29b1c 100644 --- a/core/embed/trezorhal/stm32f4/image.c +++ b/core/embed/lib/image.c @@ -93,12 +93,14 @@ secbool check_image_model(const image_header *const hdr) { } #endif +#ifndef TREZOR_EMULATOR if (hdr->hw_model != HW_MODEL) { return secfalse; } if (hdr->hw_revision != HW_REVISION) { return secfalse; } +#endif return sectrue; } @@ -215,14 +217,15 @@ secbool check_single_hash(const uint8_t *const hash, const uint8_t *const data, blake2s(data, len, h, BLAKE2S_DIGEST_LENGTH); return sectrue * (0 == memcmp(h, hash, BLAKE2S_DIGEST_LENGTH)); } - +// secbool check_image_contents(const image_header *const hdr, uint32_t firstskip, - const uint8_t *sectors, int blocks) { - if (0 == sectors || blocks < 1) { + const flash_area_t *area) { + if (0 == area) { return secfalse; } + const void *data = - flash_get_address(sectors[0], firstskip, IMAGE_CHUNK_SIZE - firstskip); + flash_area_get_address(area, firstskip, IMAGE_CHUNK_SIZE - firstskip); if (!data) { return secfalse; } @@ -232,22 +235,24 @@ secbool check_image_contents(const image_header *const hdr, uint32_t firstskip, MIN(remaining, IMAGE_CHUNK_SIZE - firstskip))) { return secfalse; } - int block = 1; + remaining -= IMAGE_CHUNK_SIZE - firstskip; + + int chunk = 1; + while (remaining > 0) { - if (block >= blocks) { - return secfalse; - } - data = flash_get_address(sectors[block], 0, IMAGE_CHUNK_SIZE); + data = flash_area_get_address(area, chunk * IMAGE_CHUNK_SIZE, + IMAGE_CHUNK_SIZE); if (!data) { return secfalse; } - if (sectrue != check_single_hash(hdr->hashes + block * 32, data, + if (sectrue != check_single_hash(hdr->hashes + chunk * 32, data, MIN(remaining, IMAGE_CHUNK_SIZE))) { return secfalse; } - block++; + chunk++; remaining -= IMAGE_CHUNK_SIZE; } + return sectrue; } diff --git a/core/embed/trezorhal/image.h b/core/embed/lib/image.h similarity index 89% rename from core/embed/trezorhal/image.h rename to core/embed/lib/image.h index ff29c4516..ce31fc87e 100644 --- a/core/embed/trezorhal/image.h +++ b/core/embed/lib/image.h @@ -21,22 +21,17 @@ #define __TREZORHAL_IMAGE_H__ #include +#include "flash.h" #include "secbool.h" -#define BOARDLOADER_START 0x08000000 -#define BOOTLOADER_START 0x08020000 -#define FIRMWARE_START 0x08040000 - #define IMAGE_HEADER_SIZE 0x400 // size of the bootloader or firmware header #define IMAGE_SIG_SIZE 65 #define IMAGE_CHUNK_SIZE (128 * 1024) #define IMAGE_INIT_CHUNK_SIZE (16 * 1024) #define BOOTLOADER_IMAGE_MAGIC 0x425A5254 // TRZB -#define BOOTLOADER_IMAGE_MAXSIZE (BOOTLOADER_SECTORS_COUNT * IMAGE_CHUNK_SIZE) #define FIRMWARE_IMAGE_MAGIC 0x465A5254 // TRZF -#define FIRMWARE_IMAGE_MAXSIZE (FIRMWARE_SECTORS_COUNT * IMAGE_CHUNK_SIZE) typedef struct { uint32_t magic; @@ -104,8 +99,8 @@ secbool __wur check_single_hash(const uint8_t *const hash, const uint8_t *const data, int len); secbool __wur check_image_contents(const image_header *const hdr, - uint32_t firstskip, const uint8_t *sectors, - int blocks); + uint32_t firstskip, + const flash_area_t *area); void get_image_fingerprint(const image_header *const hdr, uint8_t *const out); diff --git a/core/embed/lib/unit_variant.c b/core/embed/lib/unit_variant.c index d766f6098..8e1b51a04 100644 --- a/core/embed/lib/unit_variant.c +++ b/core/embed/lib/unit_variant.c @@ -1,5 +1,6 @@ #include "unit_variant.h" #include "flash.h" +#include "model.h" static uint8_t unit_variant_color = 0; static bool unit_variant_btconly = false; diff --git a/core/embed/models/layout_common.h b/core/embed/models/layout_common.h new file mode 100644 index 000000000..a7d464465 --- /dev/null +++ b/core/embed/models/layout_common.h @@ -0,0 +1,22 @@ +#ifndef LAYOUT_COMMON_H +#define LAYOUT_COMMON_H + +#include "flash.h" + +// OTP blocks allocation +#define FLASH_OTP_BLOCK_BATCH 0 +#define FLASH_OTP_BLOCK_BOOTLOADER_VERSION 1 +#define FLASH_OTP_BLOCK_VENDOR_HEADER_LOCK 2 +#define FLASH_OTP_BLOCK_RANDOMNESS 3 +#define FLASH_OTP_BLOCK_DEVICE_VARIANT 4 + +#define STORAGE_AREAS_COUNT (2) + +extern const flash_area_t STORAGE_AREAS[STORAGE_AREAS_COUNT]; +extern const flash_area_t BOARDLOADER_AREA; +extern const flash_area_t BOOTLOADER_AREA; +extern const flash_area_t FIRMWARE_AREA; +extern const flash_area_t WIPE_AREA; +extern const flash_area_t ALL_WIPE_AREA; + +#endif diff --git a/core/embed/models/model.h b/core/embed/models/model.h index 1fb10ac11..0739cdf02 100644 --- a/core/embed/models/model.h +++ b/core/embed/models/model.h @@ -1,6 +1,8 @@ #ifndef MODELS_MODEL_H_ #define MODELS_MODEL_H_ +#include "layout_common.h" + #if defined TREZOR_MODEL_1 #include "model_T1B1.h" #elif defined TREZOR_MODEL_T diff --git a/core/embed/models/model_D001.h b/core/embed/models/model_D001.h index 91d626f31..9840ea688 100644 --- a/core/embed/models/model_D001.h +++ b/core/embed/models/model_D001.h @@ -18,4 +18,11 @@ (const uint8_t *)"\x63\x55\x69\x1c\x17\x8a\x8f\xf9\x10\x07\xa7\x47\x8a\xfb\x95\x5e\xf7\x35\x2c\x63\xe7\xb2\x57\x03\x98\x4c\xf7\x8b\x26\xe2\x1a\x56", \ (const uint8_t *)"\xee\x93\xa4\xf6\x6f\x8d\x16\xb8\x19\xbb\x9b\xeb\x9f\xfc\xcd\xfc\xdc\x14\x12\xe8\x7f\xee\x6a\x32\x4c\x2a\x99\xa1\xe0\xe6\x71\x48", +#define BOARDLOADER_START 0x08000000 +#define BOOTLOADER_START 0x08020000 +#define FIRMWARE_START 0x08040000 + +#define BOOTLOADER_IMAGE_MAXSIZE (128 * 1024 * 1) // 128 KB +#define FIRMWARE_IMAGE_MAXSIZE (128 * 1024 * 13) // 1664 KB + #endif diff --git a/core/embed/models/model_D001_layout.c b/core/embed/models/model_D001_layout.c new file mode 120000 index 000000000..e68955d8d --- /dev/null +++ b/core/embed/models/model_D001_layout.c @@ -0,0 +1 @@ +model_T2T1_layout.c \ No newline at end of file diff --git a/core/embed/models/model_T1B1.h b/core/embed/models/model_T1B1.h index b55cf1a3c..c138b4711 100644 --- a/core/embed/models/model_T1B1.h +++ b/core/embed/models/model_T1B1.h @@ -7,4 +7,10 @@ #define MODEL_NAME_QSTR MP_QSTR_1 #define MODEL_INTERNAL_NAME_QSTR MP_QSTR_T1B1 +#define BOOTLOADER_START 0x08000000 +#define FIRMWARE_START 0x08010000 + +#define BOOTLOADER_IMAGE_MAXSIZE (32 * 1024 * 1) // 32 KB +#define FIRMWARE_IMAGE_MAXSIZE (64 * 1024 * 15) // 960 KB + #endif diff --git a/core/embed/models/model_T1B1_layout.c b/core/embed/models/model_T1B1_layout.c new file mode 100644 index 000000000..5532b2671 --- /dev/null +++ b/core/embed/models/model_T1B1_layout.c @@ -0,0 +1,39 @@ +#include "flash.h" +#include "model.h" + +const flash_area_t STORAGE_AREAS[STORAGE_AREAS_COUNT] = { + { + .num_subareas = 1, + .subarea[0] = + { + .first_sector = 2, + .num_sectors = 1, + }, + }, + { + .num_subareas = 1, + .subarea[0] = + { + .first_sector = 3, + .num_sectors = 1, + }, + }, +}; + +const flash_area_t BOOTLOADER_AREA = { + .num_subareas = 1, + .subarea[0] = + { + .first_sector = 0, + .num_sectors = 2, + }, +}; + +const flash_area_t FIRMWARE_AREA = { + .num_subareas = 1, + .subarea[0] = + { + .first_sector = 4, + .num_sectors = 8, + }, +}; diff --git a/core/embed/models/model_T2B1.h b/core/embed/models/model_T2B1.h index 99a3f22aa..ce3795a37 100644 --- a/core/embed/models/model_T2B1.h +++ b/core/embed/models/model_T2B1.h @@ -18,4 +18,11 @@ (const uint8_t *)"\xd2\xde\xf6\x91\xc1\xe9\xd8\x09\xd8\x19\x0c\xf7\xaf\x93\x5c\x10\x68\x8f\x68\x98\x34\x79\xb4\xee\x9a\xba\xc1\x91\x04\x87\x8e\xc1", \ (const uint8_t *)"\x07\xc8\x51\x34\x94\x6b\xf8\x9f\xa1\x9b\xdc\x2c\x5e\x5f\xf9\xce\x01\x29\x65\x08\xee\x08\x63\xd0\xff\x6d\x63\x33\x1d\x1a\x25\x16", +#define BOARDLOADER_START 0x08000000 +#define BOOTLOADER_START 0x08020000 +#define FIRMWARE_START 0x08040000 + +#define BOOTLOADER_IMAGE_MAXSIZE (128 * 1024 * 1) // 128 KB +#define FIRMWARE_IMAGE_MAXSIZE (128 * 1024 * 13) // 1664 KB + #endif diff --git a/core/embed/models/model_T2B1_layout.c b/core/embed/models/model_T2B1_layout.c new file mode 120000 index 000000000..e68955d8d --- /dev/null +++ b/core/embed/models/model_T2B1_layout.c @@ -0,0 +1 @@ +model_T2T1_layout.c \ No newline at end of file diff --git a/core/embed/models/model_T2T1.h b/core/embed/models/model_T2T1.h index 3b0453186..0af3ebfe3 100644 --- a/core/embed/models/model_T2T1.h +++ b/core/embed/models/model_T2T1.h @@ -18,4 +18,11 @@ (const uint8_t *)"\x80\xd0\x36\xb0\x87\x39\xb8\x46\xf4\xcb\x77\x59\x30\x78\xde\xb2\x5d\xc9\x48\x7a\xed\xcf\x52\xe3\x0b\x4f\xb7\xcd\x70\x24\x17\x8a", \ (const uint8_t *)"\xb8\x30\x7a\x71\xf5\x52\xc6\x0a\x4c\xbb\x31\x7f\xf4\x8b\x82\xcd\xbf\x6b\x6b\xb5\xf0\x4c\x92\x0f\xec\x7b\xad\xf0\x17\x88\x37\x51", +#define BOARDLOADER_START 0x08000000 +#define BOOTLOADER_START 0x08020000 +#define FIRMWARE_START 0x08040000 + +#define BOOTLOADER_IMAGE_MAXSIZE (128 * 1024 * 1) // 128 KB +#define FIRMWARE_IMAGE_MAXSIZE (128 * 1024 * 13) // 1664 KB + #endif diff --git a/core/embed/models/model_T2T1_layout.c b/core/embed/models/model_T2T1_layout.c new file mode 100644 index 000000000..b845ffa56 --- /dev/null +++ b/core/embed/models/model_T2T1_layout.c @@ -0,0 +1,82 @@ +#include "flash.h" +#include "model.h" + +const flash_area_t STORAGE_AREAS[STORAGE_AREAS_COUNT] = { + { + .num_subareas = 1, + .subarea[0] = + { + .first_sector = 4, + .num_sectors = 1, + }, + }, + { + .num_subareas = 1, + .subarea[0] = + { + .first_sector = 16, + .num_sectors = 1, + }, + }, +}; + +const flash_area_t BOARDLOADER_AREA = { + .num_subareas = 1, + .subarea[0] = + { + .first_sector = 0, + .num_sectors = 3, + }, +}; + +const flash_area_t BOOTLOADER_AREA = { + .num_subareas = 1, + .subarea[0] = + { + .first_sector = 5, + .num_sectors = 1, + }, +}; + +const flash_area_t FIRMWARE_AREA = { + .num_subareas = 2, + .subarea[0] = + { + .first_sector = 6, + .num_sectors = 6, + }, + .subarea[1] = + { + .first_sector = 17, + .num_sectors = 7, + }, +}; + +const flash_area_t WIPE_AREA = { + .num_subareas = 3, + .subarea[0] = + { + .first_sector = 4, + .num_sectors = 1, + }, + .subarea[1] = + { + .first_sector = 6, + .num_sectors = + 9, // sector 15 skipped due to bootloader MPU settings + }, + .subarea[2] = + { + .first_sector = 16, + .num_sectors = 8, + }, +}; + +const flash_area_t ALL_WIPE_AREA = { + .num_subareas = 1, + .subarea[0] = + { + .first_sector = 3, + .num_sectors = 21, + }, +}; diff --git a/core/embed/prodtest/main.c b/core/embed/prodtest/main.c index d04e874f6..1c63fbe81 100644 --- a/core/embed/prodtest/main.c +++ b/core/embed/prodtest/main.c @@ -29,6 +29,7 @@ #include "flash.h" #include "i2c.h" #include "mini_printf.h" +#include "model.h" #include "random_delays.h" #include "rng.h" #include "sbu.h" @@ -426,9 +427,9 @@ static void test_wipe(void) { // erase start of the firmware (metadata) -> invalidate FW ensure(flash_unlock_write(), NULL); for (int i = 0; i < 1024 / sizeof(uint32_t); i++) { - ensure(flash_write_word(FLASH_SECTOR_FIRMWARE_START, i * sizeof(uint32_t), - 0x00000000), - NULL); + ensure( + flash_area_write_word(&FIRMWARE_AREA, i * sizeof(uint32_t), 0x00000000), + NULL); } ensure(flash_lock_write(), NULL); display_clear(); diff --git a/core/embed/reflash/main.c b/core/embed/reflash/main.c index 10a2fb1f0..ac26ec64e 100644 --- a/core/embed/reflash/main.c +++ b/core/embed/reflash/main.c @@ -27,6 +27,7 @@ #include "display.h" #include "flash.h" #include "image.h" +#include "model.h" #include "rng.h" #include "sbu.h" #include "sdcard.h" @@ -35,7 +36,7 @@ static void progress_callback(int pos, int len) { display_printf("."); } -static void flash_from_sdcard(uint8_t sector, uint32_t source, +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)]; @@ -50,9 +51,10 @@ static void flash_from_sdcard(uint8_t sector, 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); j++) { - ensure(flash_write_word( - sector, i * SDCARD_BLOCK_SIZE + j * sizeof(uint32_t), buf[j]), + 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]), NULL); } } @@ -70,14 +72,10 @@ int main(void) { display_printf("updating boardloader + bootloader\n"); - static const uint8_t sectors[] = { - FLASH_SECTOR_BOARDLOADER_START, - 1, - FLASH_SECTOR_BOARDLOADER_END, - FLASH_SECTOR_BOOTLOADER, - }; display_printf("erasing sectors"); - ensure(flash_erase_sectors(sectors, sizeof(sectors), progress_callback), + ensure(flash_area_erase(&BOARDLOADER_AREA, progress_callback), + "flash_erase_sectors"); + ensure(flash_area_erase(&BOOTLOADER_AREA, progress_callback), "flash_erase_sectors"); display_printf("\n"); display_printf("erased\n"); @@ -90,12 +88,8 @@ int main(void) { #define BOARDLOADER_TOTAL_SIZE (3 * BOARDLOADER_CHUNK_SIZE) #define BOOTLOADER_TOTAL_SIZE (128 * 1024) - flash_from_sdcard(FLASH_SECTOR_BOARDLOADER_START, 0 * BOARDLOADER_CHUNK_SIZE, - BOARDLOADER_CHUNK_SIZE); - flash_from_sdcard(1, 1 * BOARDLOADER_CHUNK_SIZE, BOARDLOADER_CHUNK_SIZE); - flash_from_sdcard(FLASH_SECTOR_BOARDLOADER_END, 2 * BOARDLOADER_CHUNK_SIZE, - BOARDLOADER_CHUNK_SIZE); - flash_from_sdcard(FLASH_SECTOR_BOOTLOADER, BOARDLOADER_TOTAL_SIZE, + flash_from_sdcard(&BOARDLOADER_AREA, 0, BOARDLOADER_TOTAL_SIZE); + flash_from_sdcard(&BOOTLOADER_AREA, BOARDLOADER_TOTAL_SIZE, BOOTLOADER_TOTAL_SIZE); display_printf("done\n"); diff --git a/core/embed/trezorhal/flash.h b/core/embed/trezorhal/flash.h index e874e7f02..d3e094850 100644 --- a/core/embed/trezorhal/flash.h +++ b/core/embed/trezorhal/flash.h @@ -22,100 +22,40 @@ #include #include +#include "platform.h" #include "secbool.h" -// see docs/memory.md for more information - -#if defined STM32F427xx || defined STM32F429xx -#define FLASH_SECTOR_COUNT 24 -#elif defined STM32F405xx -#define FLASH_SECTOR_COUNT 12 -#else -#error Unsupported MCU -#endif - -#define FLASH_SECTOR_BOARDLOADER_START 0 -// 1 -#define FLASH_SECTOR_BOARDLOADER_END 2 - -// 3 - -#if defined TREZOR_MODEL_T || defined TREZOR_MODEL_R || \ - defined TREZOR_MODEL_DISC1 -#define FLASH_SECTOR_STORAGE_1 4 -#define FLASH_SECTOR_STORAGE_2 16 -#elif defined TREZOR_MODEL_1 -#define FLASH_SECTOR_STORAGE_1 2 -#define FLASH_SECTOR_STORAGE_2 3 -#else -#error Unknown Trezor model -#endif - -#define FLASH_SECTOR_BOOTLOADER 5 - -#define FLASH_SECTOR_FIRMWARE_START 6 -// 7 -// 8 -// 9 -// 10 -#define FLASH_SECTOR_FIRMWARE_END 11 - -#define FLASH_SECTOR_UNUSED_START 12 -// 13 -// 14 -#define FLASH_SECTOR_UNUSED_END 15 - -#define FLASH_SECTOR_FIRMWARE_EXTRA_START 17 -// 18 -// 19 -// 20 -// 21 -// 22 -#define FLASH_SECTOR_FIRMWARE_EXTRA_END 23 - -#define BOOTLOADER_SECTORS_COUNT (1) -#define STORAGE_SECTORS_COUNT (2) -#define FIRMWARE_SECTORS_COUNT (6 + 7) - -extern const uint8_t STORAGE_SECTORS[STORAGE_SECTORS_COUNT]; -extern const uint8_t FIRMWARE_SECTORS[FIRMWARE_SECTORS_COUNT]; - -// note: FLASH_SR_RDERR is STM32F42xxx and STM32F43xxx specific (STM32F427) -// (reference RM0090 section 3.7.5) -#if !defined STM32F427xx && !defined STM32F429xx -#define FLASH_SR_RDERR 0 -#endif - -#define FLASH_STATUS_ALL_FLAGS \ - (FLASH_SR_RDERR | FLASH_SR_PGSERR | FLASH_SR_PGPERR | FLASH_SR_PGAERR | \ - FLASH_SR_WRPERR | FLASH_SR_SOP | FLASH_SR_EOP) - -void flash_init(void); - -uint32_t flash_wait_and_clear_status_flags(void); - -secbool __wur flash_unlock_write(void); -secbool __wur flash_lock_write(void); - -const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size); -uint32_t flash_sector_size(uint8_t sector); -secbool __wur flash_erase_sectors(const uint8_t *sectors, int len, - void (*progress)(int pos, int len)); -static inline secbool flash_erase(uint8_t sector) { - return flash_erase_sectors(§or, 1, NULL); -} -secbool __wur flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data); -secbool __wur flash_write_word(uint8_t sector, uint32_t offset, uint32_t data); - #define FLASH_OTP_NUM_BLOCKS 16 #define FLASH_OTP_BLOCK_SIZE 32 -// OTP blocks allocation -#define FLASH_OTP_BLOCK_BATCH 0 -#define FLASH_OTP_BLOCK_BOOTLOADER_VERSION 1 -#define FLASH_OTP_BLOCK_VENDOR_HEADER_LOCK 2 -#define FLASH_OTP_BLOCK_RANDOMNESS 3 -#define FLASH_OTP_BLOCK_DEVICE_VARIANT 4 +/** + * Flash driver interface is designed to abstract away differences between + * various MCUs used in Trezor devices. + * + * Generally, flash memory is divided into sectors. On different MCUs, sectors + * may have different sizes, and therefore, different number of sectors are used + * for a given purpose. For example, on STM32F4, the sectors are relatively + * large so we use single sector for Storage. On STM32U5, the sectors are + * smaller, so we use multiple sectors for the Storage. Storage implementation + * should not care about this, and should use flash_area_t interface to access + * the flash memory. + * + * flash_area_t represents a location in flash memory. It may be contiguous, or + * it may be composed of multiple non-contiguous subareas. + * + * flash_subarea_t represents a contiguous area in flash memory, specified by + * first_sector and num_sectors. + */ + +#include "flash_common.h" + +void flash_init(void); + +secbool flash_write_byte(uint16_t sector, uint32_t offset, uint8_t data); + +secbool flash_write_word(uint16_t sector, uint32_t offset, uint32_t data); + +uint32_t flash_wait_and_clear_status_flags(void); secbool __wur flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data, uint8_t datalen); diff --git a/core/embed/trezorhal/stm32f4/common.c b/core/embed/trezorhal/stm32f4/common.c index fc27142fe..3af562b94 100644 --- a/core/embed/trezorhal/stm32f4/common.c +++ b/core/embed/trezorhal/stm32f4/common.c @@ -23,6 +23,8 @@ #include "common.h" #include "display.h" +#include "model.h" + #ifdef FANCY_FATAL_ERROR #include "rust_ui.h" #endif diff --git a/core/embed/trezorhal/stm32f4/flash.c b/core/embed/trezorhal/stm32f4/flash.c index c85b58669..d83887840 100644 --- a/core/embed/trezorhal/stm32f4/flash.c +++ b/core/embed/trezorhal/stm32f4/flash.c @@ -24,6 +24,24 @@ #include "common.h" #include "flash.h" +#if defined STM32F427xx || defined STM32F429xx +#define FLASH_SECTOR_COUNT 24 +#elif defined STM32F405x +#define FLASH_SECTOR_COUNT 12 +#else +#error Unknown MCU +#endif + +// note: FLASH_SR_RDERR is STM32F42xxx and STM32F43xxx specific (STM32F427) +// (reference RM0090 section 3.7.5) +#if !defined STM32F427xx && !defined STM32F429xx +#define FLASH_SR_RDERR 0 +#endif + +#define FLASH_STATUS_ALL_FLAGS \ + (FLASH_SR_RDERR | FLASH_SR_PGSERR | FLASH_SR_PGPERR | FLASH_SR_PGAERR | \ + FLASH_SR_WRPERR | FLASH_SR_SOP | FLASH_SR_EOP) + // see docs/memory.md for more information static const uint32_t FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT + 1] = { @@ -60,26 +78,14 @@ static const uint32_t FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT + 1] = { #endif }; -const uint8_t FIRMWARE_SECTORS[FIRMWARE_SECTORS_COUNT] = { - FLASH_SECTOR_FIRMWARE_START, - 7, - 8, - 9, - 10, - FLASH_SECTOR_FIRMWARE_END, - FLASH_SECTOR_FIRMWARE_EXTRA_START, - 18, - 19, - 20, - 21, - 22, - FLASH_SECTOR_FIRMWARE_EXTRA_END, -}; - -const uint8_t STORAGE_SECTORS[STORAGE_SECTORS_COUNT] = { - FLASH_SECTOR_STORAGE_1, - FLASH_SECTOR_STORAGE_2, -}; +uint32_t flash_wait_and_clear_status_flags(void) { + while (FLASH->SR & FLASH_SR_BSY) + ; // wait for all previous flash operations to complete + const uint32_t result = + FLASH->SR & FLASH_STATUS_ALL_FLAGS; // get the current status flags + FLASH->SR |= FLASH_STATUS_ALL_FLAGS; // clear all status flags + return result; +} secbool flash_unlock_write(void) { HAL_FLASH_Unlock(); @@ -92,7 +98,7 @@ secbool flash_lock_write(void) { return sectrue; } -const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size) { +const void *flash_get_address(uint16_t sector, uint32_t offset, uint32_t size) { if (sector >= FLASH_SECTOR_COUNT) { return NULL; } @@ -104,48 +110,64 @@ const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size) { return (const void *)addr; } -uint32_t flash_sector_size(uint8_t sector) { +uint32_t flash_sector_size(uint16_t sector) { if (sector >= FLASH_SECTOR_COUNT) { return 0; } return FLASH_SECTOR_TABLE[sector + 1] - FLASH_SECTOR_TABLE[sector]; } -secbool flash_erase_sectors(const uint8_t *sectors, int len, - void (*progress)(int pos, int len)) { +secbool flash_area_erase_bulk(const flash_area_t *area, int count, + void (*progress)(int pos, int len)) { ensure(flash_unlock_write(), NULL); - FLASH_EraseInitTypeDef EraseInitStruct; + FLASH_EraseInitTypeDef EraseInitStruct = {0}; EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS; EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3; EraseInitStruct.NbSectors = 1; - if (progress) { - progress(0, len); + + int total_sectors = 0; + int done_sectors = 0; + for (int a = 0; a < count; a++) { + for (int i = 0; i < area[a].num_subareas; i++) { + total_sectors += area[a].subarea[i].num_sectors; + } } - for (int i = 0; i < len; i++) { - EraseInitStruct.Sector = sectors[i]; - uint32_t SectorError; - if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) { - ensure(flash_lock_write(), NULL); - return secfalse; - } - // check whether the sector was really deleted (contains only 0xFF) - const uint32_t addr_start = FLASH_SECTOR_TABLE[sectors[i]], - addr_end = FLASH_SECTOR_TABLE[sectors[i] + 1]; - for (uint32_t addr = addr_start; addr < addr_end; addr += 4) { - if (*((const uint32_t *)addr) != 0xFFFFFFFF) { - ensure(flash_lock_write(), NULL); - return secfalse; + if (progress) { + progress(0, total_sectors); + } + + for (int a = 0; a < count; a++) { + for (int s = 0; s < area[a].num_subareas; s++) { + for (int i = 0; i < area[a].subarea[s].num_sectors; i++) { + int sector = area[a].subarea[s].first_sector + i; + + EraseInitStruct.Sector = sector; + uint32_t SectorError; + if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) { + ensure(flash_lock_write(), NULL); + return secfalse; + } + // check whether the sector was really deleted (contains only 0xFF) + const uint32_t addr_start = FLASH_SECTOR_TABLE[sector], + addr_end = FLASH_SECTOR_TABLE[sector + 1]; + for (uint32_t addr = addr_start; addr < addr_end; addr += 4) { + if (*((const uint32_t *)addr) != 0xFFFFFFFF) { + ensure(flash_lock_write(), NULL); + return secfalse; + } + } + done_sectors++; + if (progress) { + progress(done_sectors, total_sectors); + } } } - if (progress) { - progress(i + 1, len); - } } ensure(flash_lock_write(), NULL); return sectrue; } -secbool flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data) { +secbool flash_write_byte(uint16_t sector, uint32_t offset, uint8_t data) { uint32_t address = (uint32_t)flash_get_address(sector, offset, 1); if (address == 0) { return secfalse; @@ -162,7 +184,7 @@ secbool flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data) { return sectrue; } -secbool flash_write_word(uint8_t sector, uint32_t offset, uint32_t data) { +secbool flash_write_word(uint16_t sector, uint32_t offset, uint32_t data) { uint32_t address = (uint32_t)flash_get_address(sector, offset, 4); if (address == 0) { return secfalse; diff --git a/core/embed/trezorhal/stm32f4/lowlevel.c b/core/embed/trezorhal/stm32f4/lowlevel.c index 3cda60216..6170e69fb 100644 --- a/core/embed/trezorhal/stm32f4/lowlevel.c +++ b/core/embed/trezorhal/stm32f4/lowlevel.c @@ -57,15 +57,6 @@ #define OPTION_BYTES_BANK1_WRP (*(volatile uint16_t* const)0x1FFFC008U) #define OPTION_BYTES_BANK2_WRP (*(volatile uint16_t* const)0x1FFEC008U) -uint32_t flash_wait_and_clear_status_flags(void) { - while (FLASH->SR & FLASH_SR_BSY) - ; // wait for all previous flash operations to complete - const uint32_t result = - FLASH->SR & FLASH_STATUS_ALL_FLAGS; // get the current status flags - FLASH->SR |= FLASH_STATUS_ALL_FLAGS; // clear all status flags - return result; -} - secbool flash_check_option_bytes(void) { flash_wait_and_clear_status_flags(); // check values stored in flash interface registers diff --git a/core/embed/trezorhal/stm32f4/platform.h b/core/embed/trezorhal/stm32f4/platform.h index b2d87e862..9af69c2df 100644 --- a/core/embed/trezorhal/stm32f4/platform.h +++ b/core/embed/trezorhal/stm32f4/platform.h @@ -23,6 +23,8 @@ #include STM32_HAL_H #include +#define FLASH_BYTE_ACCESS 1 + typedef enum { CLOCK_180_MHZ = 0, CLOCK_168_MHZ = 1, diff --git a/core/embed/trezorhal/unix/flash.c b/core/embed/trezorhal/unix/flash.c index 69a2d7c7e..c423addd3 100644 --- a/core/embed/trezorhal/unix/flash.c +++ b/core/embed/trezorhal/unix/flash.c @@ -28,12 +28,21 @@ #include "common.h" #include "flash.h" +#include "model.h" #include "profile.h" #ifndef FLASH_FILE #define FLASH_FILE profile_flash_path() #endif +#if defined TREZOR_MODEL_T || defined TREZOR_MODEL_R +#define FLASH_SECTOR_COUNT 24 +#elif defined TREZOR_MODEL_1 +#define FLASH_SECTOR_COUNT 12 +#else +#error Unknown MCU +#endif + static const uint32_t FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT + 1] = { [0] = 0x08000000, // - 0x08003FFF | 16 KiB [1] = 0x08004000, // - 0x08007FFF | 16 KiB @@ -68,27 +77,6 @@ static const uint32_t FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT + 1] = { #endif }; -const uint8_t FIRMWARE_SECTORS[FIRMWARE_SECTORS_COUNT] = { - FLASH_SECTOR_FIRMWARE_START, - 7, - 8, - 9, - 10, - FLASH_SECTOR_FIRMWARE_END, - FLASH_SECTOR_FIRMWARE_EXTRA_START, - 18, - 19, - 20, - 21, - 22, - FLASH_SECTOR_FIRMWARE_EXTRA_END, -}; - -const uint8_t STORAGE_SECTORS[STORAGE_SECTORS_COUNT] = { - FLASH_SECTOR_STORAGE_1, - FLASH_SECTOR_STORAGE_2, -}; - static uint8_t *FLASH_BUFFER = NULL; static uint32_t FLASH_SIZE; @@ -145,7 +133,7 @@ secbool flash_unlock_write(void) { return sectrue; } secbool flash_lock_write(void) { return sectrue; } -const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size) { +const void *flash_get_address(uint16_t sector, uint32_t offset, uint32_t size) { if (sector >= FLASH_SECTOR_COUNT) { return NULL; } @@ -157,32 +145,52 @@ const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size) { return FLASH_BUFFER + addr - FLASH_SECTOR_TABLE[0]; } -uint32_t flash_sector_size(uint8_t sector) { +uint32_t flash_sector_size(uint16_t sector) { if (sector >= FLASH_SECTOR_COUNT) { return 0; } return FLASH_SECTOR_TABLE[sector + 1] - FLASH_SECTOR_TABLE[sector]; } -secbool flash_erase_sectors(const uint8_t *sectors, int len, - void (*progress)(int pos, int len)) { - if (progress) { - progress(0, len); - } - for (int i = 0; i < len; i++) { - const uint8_t sector = sectors[i]; - const uint32_t offset = FLASH_SECTOR_TABLE[sector] - FLASH_SECTOR_TABLE[0]; - const uint32_t size = - FLASH_SECTOR_TABLE[sector + 1] - FLASH_SECTOR_TABLE[sector]; - memset(FLASH_BUFFER + offset, 0xFF, size); - if (progress) { - progress(i + 1, len); +secbool flash_area_erase_bulk(const flash_area_t *area, int count, + void (*progress)(int pos, int len)) { + ensure(flash_unlock_write(), NULL); + + int total_sectors = 0; + int done_sectors = 0; + for (int a = 0; a < count; a++) { + for (int i = 0; i < area[a].num_subareas; i++) { + total_sectors += area[a].subarea[i].num_sectors; } } + + if (progress) { + progress(0, total_sectors); + } + + for (int a = 0; a < count; a++) { + for (int s = 0; s < area[a].num_subareas; s++) { + for (int i = 0; i < area[a].subarea[s].num_sectors; i++) { + int sector = area[a].subarea[s].first_sector + i; + + const uint32_t offset = + FLASH_SECTOR_TABLE[sector] - FLASH_SECTOR_TABLE[0]; + const uint32_t size = + FLASH_SECTOR_TABLE[sector + 1] - FLASH_SECTOR_TABLE[sector]; + memset(FLASH_BUFFER + offset, 0xFF, size); + + done_sectors++; + if (progress) { + progress(done_sectors, total_sectors); + } + } + } + } + ensure(flash_lock_write(), NULL); return sectrue; } -secbool flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data) { +secbool flash_write_byte(uint16_t sector, uint32_t offset, uint8_t data) { uint8_t *flash = (uint8_t *)flash_get_address(sector, offset, 1); if (!flash) { return secfalse; @@ -194,7 +202,7 @@ secbool flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data) { return sectrue; } -secbool flash_write_word(uint8_t sector, uint32_t offset, uint32_t data) { +secbool flash_write_word(uint16_t sector, uint32_t offset, uint32_t data) { if (offset % sizeof(uint32_t)) { // we write only at 4-byte boundary return secfalse; } diff --git a/core/embed/trezorhal/unix/image.c b/core/embed/trezorhal/unix/image.c deleted file mode 120000 index 8c435077c..000000000 --- a/core/embed/trezorhal/unix/image.c +++ /dev/null @@ -1 +0,0 @@ -../stm32f4/image.c \ No newline at end of file diff --git a/core/embed/trezorhal/unix/platform.h b/core/embed/trezorhal/unix/platform.h index 0cab1411c..72e4ac225 100644 --- a/core/embed/trezorhal/unix/platform.h +++ b/core/embed/trezorhal/unix/platform.h @@ -1,2 +1,4 @@ +#define FLASH_BYTE_ACCESS 1 + void emulator_poll_events(void); diff --git a/core/embed/trezorhal/unix/touch/touch.c b/core/embed/trezorhal/unix/touch/touch.c index 9323d0114..56e617854 100644 --- a/core/embed/trezorhal/unix/touch/touch.c +++ b/core/embed/trezorhal/unix/touch/touch.c @@ -25,6 +25,7 @@ #ifdef USE_TOUCH #include "common.h" +#include "platform.h" #include "touch.h" extern int sdl_display_res_x, sdl_display_res_y; diff --git a/core/site_scons/boards/discovery.py b/core/site_scons/boards/discovery.py index e49f78a3d..b3d25b4f1 100644 --- a/core/site_scons/boards/discovery.py +++ b/core/site_scons/boards/discovery.py @@ -33,6 +33,9 @@ def configure( defines += [f'TREZOR_BOARD=\\"boards/{board}\\"'] defines += [f"HW_MODEL={hw_model}"] defines += [f"HW_REVISION={hw_revision}"] + sources += [ + "embed/models/model_D001_layout.c", + ] sources += [f"embed/trezorhal/stm32f4/displays/{display}"] sources += ["embed/trezorhal/stm32f4/displays/ili9341_spi.c"] sources += ["embed/trezorhal/stm32f4/dma.c"] diff --git a/core/site_scons/boards/stm32f4_common.py b/core/site_scons/boards/stm32f4_common.py index 54d65ea87..2b4d951b7 100644 --- a/core/site_scons/boards/stm32f4_common.py +++ b/core/site_scons/boards/stm32f4_common.py @@ -38,7 +38,6 @@ def stm32f4_common_files(env, defines, sources, paths): sources += [ "embed/trezorhal/stm32f4/board_capabilities.c", "embed/trezorhal/stm32f4/common.c", - "embed/trezorhal/stm32f4/image.c", "embed/trezorhal/stm32f4/flash.c", "embed/trezorhal/stm32f4/lowlevel.c", "embed/trezorhal/stm32f4/mpu.c", diff --git a/core/site_scons/boards/trezor_1.py b/core/site_scons/boards/trezor_1.py index 18683c692..75fc04503 100644 --- a/core/site_scons/boards/trezor_1.py +++ b/core/site_scons/boards/trezor_1.py @@ -31,6 +31,9 @@ def configure( defines += [f'TREZOR_BOARD=\\"boards/{board}\\"'] defines += [f"HW_MODEL={hw_model}"] defines += [f"HW_REVISION={hw_revision}"] + sources += [ + "embed/models/model_T1B1_layout.c", + ] sources += [f"embed/trezorhal/stm32f4/displays/{display}"] if "input" in features_wanted: diff --git a/core/site_scons/boards/trezor_r_v10.py b/core/site_scons/boards/trezor_r_v10.py index 1f54835e6..97f1d8eec 100644 --- a/core/site_scons/boards/trezor_r_v10.py +++ b/core/site_scons/boards/trezor_r_v10.py @@ -33,6 +33,9 @@ def configure( defines += [f'TREZOR_BOARD=\\"boards/{board}\\"'] defines += [f"HW_MODEL={hw_model}"] defines += [f"HW_REVISION={hw_revision}"] + sources += [ + "embed/models/model_T2B1_layout.c", + ] sources += [f"embed/trezorhal/stm32f4/displays/{display}"] sources += ["embed/trezorhal/stm32f4/i2c.c"] diff --git a/core/site_scons/boards/trezor_r_v3.py b/core/site_scons/boards/trezor_r_v3.py index 6267e24fc..25e2c9dec 100644 --- a/core/site_scons/boards/trezor_r_v3.py +++ b/core/site_scons/boards/trezor_r_v3.py @@ -33,6 +33,9 @@ def configure( defines += [f'TREZOR_BOARD=\\"boards/{board}\\"'] defines += [f"HW_MODEL={hw_model}"] defines += [f"HW_REVISION={hw_revision}"] + sources += [ + "embed/models/model_T2B1_layout.c", + ] sources += [f"embed/trezorhal/stm32f4/displays/{display}"] if "input" in features_wanted: diff --git a/core/site_scons/boards/trezor_r_v4.py b/core/site_scons/boards/trezor_r_v4.py index 016371491..63dab36fc 100644 --- a/core/site_scons/boards/trezor_r_v4.py +++ b/core/site_scons/boards/trezor_r_v4.py @@ -33,6 +33,9 @@ def configure( defines += [f'TREZOR_BOARD=\\"boards/{board}\\"'] defines += [f"HW_MODEL={hw_model}"] defines += [f"HW_REVISION={hw_revision}"] + sources += [ + "embed/models/model_T2B1_layout.c", + ] sources += [f"embed/trezorhal/stm32f4/displays/{display}"] if "input" in features_wanted: diff --git a/core/site_scons/boards/trezor_r_v6.py b/core/site_scons/boards/trezor_r_v6.py index 91d43edbf..6fe8f3044 100644 --- a/core/site_scons/boards/trezor_r_v6.py +++ b/core/site_scons/boards/trezor_r_v6.py @@ -33,6 +33,9 @@ def configure( defines += [f'TREZOR_BOARD=\\"boards/{board}\\"'] defines += [f"HW_MODEL={hw_model}"] defines += [f"HW_REVISION={hw_revision}"] + sources += [ + "embed/models/model_T2B1_layout.c", + ] sources += [f"embed/trezorhal/stm32f4/displays/{display}"] if "input" in features_wanted: diff --git a/core/site_scons/boards/trezor_t.py b/core/site_scons/boards/trezor_t.py index 0700970fe..2de5975f3 100644 --- a/core/site_scons/boards/trezor_t.py +++ b/core/site_scons/boards/trezor_t.py @@ -34,6 +34,9 @@ def configure( defines += [f'TREZOR_BOARD=\\"boards/{board}\\"'] defines += [f"HW_MODEL={hw_model}"] defines += [f"HW_REVISION={hw_revision}"] + sources += [ + "embed/models/model_T2T1_layout.c", + ] sources += [f"embed/trezorhal/stm32f4/displays/{display}"] sources += ["embed/trezorhal/stm32f4/backlight_pwm.c"] sources += [ diff --git a/legacy/Makefile b/legacy/Makefile index 5fb84a7ff..0a9354e03 100644 --- a/legacy/Makefile +++ b/legacy/Makefile @@ -20,6 +20,7 @@ OBJS += usb_standard.o OBJS += util.o OBJS += webusb.o OBJS += winusb.o +OBJS += vendor/trezor-storage/flash_common.o libtrezor.a: $(OBJS) diff --git a/legacy/flash.c b/legacy/flash.c index 14c6531ce..5ab770f36 100644 --- a/legacy/flash.c +++ b/legacy/flash.c @@ -25,6 +25,8 @@ #include "memory.h" #include "supervise.h" +#define STORAGE_AREAS_COUNT 2 + static const uint32_t FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT + 1] = { [0] = 0x08000000, // - 0x08003FFF | 16 KiB [1] = 0x08004000, // - 0x08007FFF | 16 KiB @@ -41,6 +43,25 @@ static const uint32_t FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT + 1] = { [12] = 0x08100000, // last element - not a valid sector }; +const flash_area_t STORAGE_AREAS[STORAGE_AREAS_COUNT] = { + { + .num_subareas = 1, + .subarea[0] = + { + .first_sector = 2, + .num_sectors = 1, + }, + }, + { + .num_subareas = 1, + .subarea[0] = + { + .first_sector = 3, + .num_sectors = 1, + }, + }, +}; + static secbool flash_check_success(uint32_t status) { return (status & (FLASH_SR_PGAERR | FLASH_SR_PGPERR | FLASH_SR_PGSERR | FLASH_SR_WRPERR)) @@ -55,7 +76,7 @@ secbool flash_unlock_write(void) { secbool flash_lock_write(void) { return flash_check_success(svc_flash_lock()); } -const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size) { +const void *flash_get_address(uint16_t sector, uint32_t offset, uint32_t size) { if (sector >= FLASH_SECTOR_COUNT) { return NULL; } @@ -67,29 +88,13 @@ const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size) { return (const void *)FLASH_PTR(addr); } -uint32_t flash_sector_size(uint8_t sector) { +uint32_t flash_sector_size(uint16_t sector) { if (sector >= FLASH_SECTOR_COUNT) { return 0; } return FLASH_SECTOR_TABLE[sector + 1] - FLASH_SECTOR_TABLE[sector]; } -secbool flash_erase(uint8_t sector) { - ensure(flash_unlock_write(), NULL); - svc_flash_erase_sector(sector); - ensure(flash_lock_write(), NULL); - - // Check whether the sector was really deleted (contains only 0xFF). - const uint32_t addr_start = FLASH_SECTOR_TABLE[sector], - addr_end = FLASH_SECTOR_TABLE[sector + 1]; - for (uint32_t addr = addr_start; addr < addr_end; addr += 4) { - if (*((const uint32_t *)FLASH_PTR(addr)) != 0xFFFFFFFF) { - return secfalse; - } - } - return sectrue; -} - secbool flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data) { uint8_t *address = (uint8_t *)flash_get_address(sector, offset, 1); if (address == NULL) { @@ -133,3 +138,43 @@ secbool flash_write_word(uint8_t sector, uint32_t offset, uint32_t data) { return sectrue; } + +secbool flash_area_erase_bulk(const flash_area_t *area, int count, + void (*progress)(int pos, int len)) { + ensure(flash_unlock_write(), NULL); + + int total_sectors = 0; + int done_sectors = 0; + for (int a = 0; a < count; a++) { + for (int i = 0; i < area[a].num_subareas; i++) { + total_sectors += area[a].subarea[i].num_sectors; + } + } + if (progress) { + progress(0, total_sectors); + } + + for (int a = 0; a < count; a++) { + for (int s = 0; s < area[a].num_subareas; s++) { + for (int i = 0; i < area[a].subarea[s].num_sectors; i++) { + int sector = area[a].subarea[s].first_sector + i; + svc_flash_erase_sector(sector); + // check whether the sector was really deleted (contains only 0xFF) + const uint32_t addr_start = FLASH_SECTOR_TABLE[sector], + addr_end = FLASH_SECTOR_TABLE[sector + 1]; + for (uint32_t addr = addr_start; addr < addr_end; addr += 4) { + if (*((const uint32_t *)FLASH_PTR(addr)) != 0xFFFFFFFF) { + ensure(flash_lock_write(), NULL); + return secfalse; + } + } + done_sectors++; + if (progress) { + progress(done_sectors, total_sectors); + } + } + } + } + ensure(flash_lock_write(), NULL); + return sectrue; +} diff --git a/legacy/flash.h b/legacy/flash.h index 819da411d..868b594fa 100644 --- a/legacy/flash.h +++ b/legacy/flash.h @@ -24,8 +24,11 @@ #include #include "secbool.h" +#define FLASH_BYTE_ACCESS 1 #define FLASH_SECTOR_COUNT 24 +#include "flash_common.h" + // note: FLASH_SR_RDERR is STM32F42xxx and STM32F43xxx specific (STM32F427) // (reference RM0090 section 3.7.5) #ifndef STM32F427xx @@ -36,12 +39,6 @@ (FLASH_SR_RDERR | FLASH_SR_PGSERR | FLASH_SR_PGPERR | FLASH_SR_PGAERR | \ FLASH_SR_WRPERR | FLASH_SR_SOP | FLASH_SR_EOP) -secbool __wur flash_unlock_write(void); -secbool __wur flash_lock_write(void); - -const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size); -uint32_t flash_sector_size(uint8_t sector); -secbool __wur flash_erase(uint8_t sector); secbool __wur flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data); secbool __wur flash_write_word(uint8_t sector, uint32_t offset, uint32_t data); diff --git a/legacy/norcow_config.h b/legacy/norcow_config.h index 83ef249ea..3a9545e19 100644 --- a/legacy/norcow_config.h +++ b/legacy/norcow_config.h @@ -33,6 +33,8 @@ */ #define NORCOW_HEADER_LEN (0) +extern const flash_area_t STORAGE_AREAS[NORCOW_SECTOR_COUNT]; + /* * Current storage version. */ diff --git a/storage/flash_common.c b/storage/flash_common.c new file mode 100644 index 000000000..79b97e279 --- /dev/null +++ b/storage/flash_common.c @@ -0,0 +1,127 @@ +#include "flash.h" + +static uint32_t flash_subarea_get_size(const flash_subarea_t *subarea) { + uint32_t size = 0; + for (int s = 0; s < subarea->num_sectors; s++) { + size += flash_sector_size(subarea->first_sector + s); + } + return size; +} + +static secbool subarea_get_sector_and_offset(const flash_subarea_t *subarea, + uint32_t offset, + uint16_t *sector_out, + uint32_t *offset_out) { + uint32_t tmp_offset = offset; + uint16_t sector = subarea->first_sector; + + // in correct subarea + for (int s = 0; s < subarea->num_sectors; s++) { + const uint32_t sector_size = flash_sector_size(sector); + if (tmp_offset < sector_size) { + *sector_out = sector; + *offset_out = tmp_offset; + return sectrue; + } + tmp_offset -= sector_size; + sector++; + } + return secfalse; +} + +uint32_t flash_area_get_size(const flash_area_t *area) { + uint32_t size = 0; + for (int i = 0; i < area->num_subareas; i++) { + size += flash_subarea_get_size(&area->subarea[i]); + } + return size; +} + +uint16_t flash_total_sectors(const flash_area_t *area) { + uint16_t total = 0; + for (int i = 0; i < area->num_subareas; i++) { + total += area->subarea[i].num_sectors; + } + return total; +} + +int32_t flash_get_sector_num(const flash_area_t *area, + uint32_t sector_inner_num) { + uint16_t sector = 0; + uint16_t remaining = sector_inner_num; + for (int i = 0; i < area->num_subareas; i++) { + if (remaining < area->subarea[i].num_sectors) { + sector = area->subarea[i].first_sector + remaining; + return sector; + } else { + remaining -= area->subarea[i].num_sectors; + } + } + + return -1; +} + +static secbool get_sector_and_offset(const flash_area_t *area, uint32_t offset, + uint16_t *sector_out, + uint32_t *offset_out) { + uint32_t tmp_offset = offset; + for (int i = 0; i < area->num_subareas; i++) { + uint32_t sub_size = flash_subarea_get_size(&area->subarea[i]); + if (tmp_offset >= sub_size) { + tmp_offset -= sub_size; + continue; + } + + return subarea_get_sector_and_offset(&area->subarea[i], tmp_offset, + sector_out, offset_out); + } + return secfalse; +} + +const void *flash_area_get_address(const flash_area_t *area, uint32_t offset, + uint32_t size) { + uint16_t sector; + uint32_t sector_offset; + + if (!get_sector_and_offset(area, offset, §or, §or_offset)) { + return NULL; + } + + return flash_get_address(sector, sector_offset, size); +} + +secbool flash_area_erase(const flash_area_t *area, + void (*progress)(int pos, int len)) { + return flash_area_erase_bulk(area, 1, progress); +} + +secbool flash_area_write_byte(const flash_area_t *area, uint32_t offset, + uint8_t data) { + uint16_t sector; + uint32_t sector_offset; + if (get_sector_and_offset(area, offset, §or, §or_offset) != sectrue) { + return secfalse; + } + return flash_write_byte(sector, sector_offset, data); +} + +secbool flash_area_write_word(const flash_area_t *area, uint32_t offset, + uint32_t data) { + uint16_t sector; + uint32_t sector_offset; + if (get_sector_and_offset(area, offset, §or, §or_offset) != sectrue) { + return secfalse; + } + 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) { + for (int i = 0; i < 4; i++) { + if (sectrue != + flash_area_write_word(area, offset + i * sizeof(uint32_t), data[i])) { + return secfalse; + } + } + return sectrue; +} diff --git a/storage/flash_common.h b/storage/flash_common.h new file mode 100644 index 000000000..140d04db1 --- /dev/null +++ b/storage/flash_common.h @@ -0,0 +1,46 @@ +#ifndef FLASH_COMMON_H +#define FLASH_COMMON_H + +#include +#include "secbool.h" + +typedef struct { + uint16_t first_sector; + uint16_t num_sectors; +} flash_subarea_t; + +typedef struct { + flash_subarea_t subarea[4]; + uint8_t num_subareas; +} flash_area_t; + +void flash_init(void); + +secbool __wur flash_unlock_write(void); +secbool __wur flash_lock_write(void); + +const void *flash_get_address(uint16_t sector, uint32_t offset, uint32_t size); +uint32_t flash_sector_size(uint16_t sector); +uint16_t flash_total_sectors(const flash_area_t *area); +int32_t flash_get_sector_num(const flash_area_t *area, + uint32_t sector_inner_num); + +const void *flash_area_get_address(const flash_area_t *area, uint32_t offset, + uint32_t size); +uint32_t flash_area_get_size(const flash_area_t *area); + +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, + void (*progress)(int pos, int len)); + +#if defined FLASH_BYTE_ACCESS +secbool __wur flash_area_write_byte(const flash_area_t *area, uint32_t offset, + uint8_t data); +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); + +#endif diff --git a/storage/norcow.c b/storage/norcow.c index 4d21ee61b..324d20c4b 100644 --- a/storage/norcow.c +++ b/storage/norcow.c @@ -43,9 +43,6 @@ #define NORCOW_STORAGE_START \ (NORCOW_HEADER_LEN + NORCOW_MAGIC_LEN + NORCOW_VERSION_LEN) -// Map from sector index to sector number. -static const uint8_t norcow_sectors[NORCOW_SECTOR_COUNT] = NORCOW_SECTORS; - // The index of the active reading sector and writing sector. These should be // equal except when storage version upgrade or compaction is in progress. static uint8_t norcow_active_sector = 0; @@ -63,7 +60,7 @@ static uint32_t norcow_free_offset = 0; */ static const void *norcow_ptr(uint8_t sector, uint32_t offset, uint32_t size) { ensure(sectrue * (sector <= NORCOW_SECTOR_COUNT), "invalid sector"); - return flash_get_address(norcow_sectors[sector], offset, size); + return flash_area_get_address(&STORAGE_AREAS[sector], offset, size); } /* @@ -82,13 +79,14 @@ static secbool norcow_write(uint8_t sector, uint32_t offset, uint32_t prefix, ensure(flash_unlock_write(), NULL); // write prefix - ensure(flash_write_word(norcow_sectors[sector], offset, prefix), NULL); + ensure(flash_area_write_word(&STORAGE_AREAS[sector], offset, prefix), NULL); offset += NORCOW_PREFIX_LEN; if (data != NULL) { // write data for (uint16_t i = 0; i < len; i++, offset++) { - ensure(flash_write_byte(norcow_sectors[sector], offset, data[i]), NULL); + ensure(flash_area_write_byte(&STORAGE_AREAS[sector], offset, data[i]), + NULL); } } else { offset += len; @@ -96,7 +94,7 @@ static secbool norcow_write(uint8_t sector, uint32_t offset, uint32_t prefix, // pad with zeroes for (; offset % NORCOW_WORD_SIZE; offset++) { - ensure(flash_write_byte(norcow_sectors[sector], offset, 0x00), NULL); + ensure(flash_area_write_byte(&STORAGE_AREAS[sector], offset, 0x00), NULL); } ensure(flash_lock_write(), NULL); @@ -114,7 +112,7 @@ static void erase_sector(uint8_t sector, secbool set_magic) { memcpy(header_backup, sector_start, sizeof(header_backup)); #endif - ensure(flash_erase(norcow_sectors[sector]), "erase failed"); + ensure(flash_area_erase(&STORAGE_AREAS[sector], NULL), "erase failed"); #if NORCOW_HEADER_LEN > 0 // Copy the sector header back. @@ -419,7 +417,6 @@ secbool norcow_set_ex(uint16_t key, const void *val, uint16_t len, return secfalse; } - const uint8_t sector_num = norcow_sectors[norcow_write_sector]; secbool ret = secfalse; const void *ptr = NULL; uint16_t len_old = 0; @@ -435,8 +432,9 @@ secbool norcow_set_ex(uint16_t key, const void *val, uint16_t len, ret = sectrue; ensure(flash_unlock_write(), NULL); for (uint16_t i = 0; i < len; i++) { - if (sectrue != flash_write_byte(sector_num, offset + i, - ((const uint8_t *)val)[i])) { + if (sectrue != + flash_area_write_byte(&STORAGE_AREAS[norcow_write_sector], + offset + i, ((const uint8_t *)val)[i])) { ret = secfalse; break; } @@ -453,13 +451,16 @@ secbool norcow_set_ex(uint16_t key, const void *val, uint16_t len, // Update the prefix to indicate that the old item has been deleted. uint32_t prefix = (uint32_t)len_old << 16; - ensure(flash_write_word(sector_num, offset - NORCOW_PREFIX_LEN, prefix), + ensure(flash_area_write_word(&STORAGE_AREAS[norcow_write_sector], + offset - NORCOW_PREFIX_LEN, prefix), NULL); // Delete the old item data. uint32_t end = offset + len_old; while (offset < end) { - ensure(flash_write_word(sector_num, offset, 0x00000000), NULL); + ensure(flash_area_write_word(&STORAGE_AREAS[norcow_write_sector], + offset, 0x00000000), + NULL); offset += NORCOW_WORD_SIZE; } @@ -489,7 +490,6 @@ secbool norcow_delete(uint16_t key) { return secfalse; } - const uint8_t sector_num = norcow_sectors[norcow_write_sector]; const void *ptr = NULL; uint16_t len = 0; if (sectrue != find_item(norcow_write_sector, key, &ptr, &len)) { @@ -504,13 +504,16 @@ secbool norcow_delete(uint16_t key) { // Update the prefix to indicate that the item has been deleted. uint32_t prefix = (uint32_t)len << 16; - ensure(flash_write_word(sector_num, offset - NORCOW_PREFIX_LEN, prefix), + ensure(flash_area_write_word(&STORAGE_AREAS[norcow_write_sector], + offset - NORCOW_PREFIX_LEN, prefix), NULL); // Delete the item data. uint32_t end = offset + len; while (offset < end) { - ensure(flash_write_word(sector_num, offset, 0x00000000), NULL); + ensure(flash_area_write_word(&STORAGE_AREAS[norcow_write_sector], offset, + 0x00000000), + NULL); offset += NORCOW_WORD_SIZE; } @@ -537,8 +540,8 @@ secbool norcow_update_word(uint16_t key, uint16_t offset, uint32_t value) { (const uint8_t *)norcow_ptr(norcow_write_sector, 0, NORCOW_SECTOR_SIZE) + offset; ensure(flash_unlock_write(), NULL); - ensure(flash_write_word(norcow_sectors[norcow_write_sector], sector_offset, - value), + ensure(flash_area_write_word(&STORAGE_AREAS[norcow_write_sector], + sector_offset, value), NULL); ensure(flash_lock_write(), NULL); return sectrue; @@ -561,10 +564,11 @@ secbool norcow_update_bytes(const uint16_t key, const uint16_t offset, (const uint8_t *)ptr - (const uint8_t *)norcow_ptr(norcow_write_sector, 0, NORCOW_SECTOR_SIZE) + offset; - uint8_t sector = norcow_sectors[norcow_write_sector]; ensure(flash_unlock_write(), NULL); for (uint16_t i = 0; i < len; i++, sector_offset++) { - ensure(flash_write_byte(sector, sector_offset, data[i]), NULL); + ensure(flash_area_write_byte(&STORAGE_AREAS[norcow_write_sector], + sector_offset, data[i]), + NULL); } ensure(flash_lock_write(), NULL); return sectrue; diff --git a/storage/tests/c/Makefile b/storage/tests/c/Makefile index df6ad656d..3171ab2b2 100644 --- a/storage/tests/c/Makefile +++ b/storage/tests/c/Makefile @@ -13,6 +13,8 @@ BASE = ../../../ SRC = storage/tests/c/flash.c SRC += storage/tests/c/common.c SRC += storage/tests/c/random_delays.c +SRC += storage/tests/c/test_layout.c +SRC += storage/flash_common.c SRC += storage/storage.c SRC += storage/norcow.c SRC += crypto/pbkdf2.c diff --git a/storage/tests/c/flash.c b/storage/tests/c/flash.c index 9f58a1435..7ca193f8d 100644 --- a/storage/tests/c/flash.c +++ b/storage/tests/c/flash.c @@ -23,6 +23,9 @@ #include "common.h" #include "flash.h" +#include "norcow_config.h" + +#define FLASH_SECTOR_COUNT 24 static const uint32_t FLASH_START = 0x08000000; static const uint32_t FLASH_END = 0x08200000; @@ -60,7 +63,14 @@ secbool flash_unlock_write(void) { return sectrue; } secbool flash_lock_write(void) { return sectrue; } -const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size) { +uint32_t flash_sector_size(uint16_t sector) { + if (sector >= FLASH_SECTOR_COUNT) { + return 0; + } + return FLASH_SECTOR_TABLE[sector + 1] - FLASH_SECTOR_TABLE[sector]; +} + +const void *flash_get_address(uint16_t sector, uint32_t offset, uint32_t size) { if (sector >= FLASH_SECTOR_COUNT) { return NULL; } @@ -72,25 +82,45 @@ const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size) { return FLASH_BUFFER + addr - FLASH_SECTOR_TABLE[0]; } -secbool flash_erase_sectors(const uint8_t *sectors, int len, - void (*progress)(int pos, int len)) { - if (progress) { - progress(0, len); - } - for (int i = 0; i < len; i++) { - const uint8_t sector = sectors[i]; - const uint32_t offset = FLASH_SECTOR_TABLE[sector] - FLASH_SECTOR_TABLE[0]; - const uint32_t size = - FLASH_SECTOR_TABLE[sector + 1] - FLASH_SECTOR_TABLE[sector]; - memset(FLASH_BUFFER + offset, 0xFF, size); - if (progress) { - progress(i + 1, len); +secbool flash_area_erase_bulk(const flash_area_t *area, int count, + void (*progress)(int pos, int len)) { + ensure(flash_unlock_write(), NULL); + + int total_sectors = 0; + int done_sectors = 0; + for (int a = 0; a < count; a++) { + for (int i = 0; i < area[a].num_subareas; i++) { + total_sectors += area[a].subarea[i].num_sectors; } } + + if (progress) { + progress(0, total_sectors); + } + + for (int a = 0; a < count; a++) { + for (int s = 0; s < area[a].num_subareas; s++) { + for (int i = 0; i < area[a].subarea[s].num_sectors; i++) { + int sector = area[a].subarea[s].first_sector + i; + + const uint32_t offset = + FLASH_SECTOR_TABLE[sector] - FLASH_SECTOR_TABLE[0]; + const uint32_t size = + FLASH_SECTOR_TABLE[sector + 1] - FLASH_SECTOR_TABLE[sector]; + memset(FLASH_BUFFER + offset, 0xFF, size); + + done_sectors++; + if (progress) { + progress(done_sectors, total_sectors); + } + } + } + } + ensure(flash_lock_write(), NULL); return sectrue; } -secbool flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data) { +secbool flash_write_byte(uint16_t sector, uint32_t offset, uint8_t data) { uint8_t *flash = (uint8_t *)flash_get_address(sector, offset, 1); if (!flash) { return secfalse; @@ -102,7 +132,7 @@ secbool flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data) { return sectrue; } -secbool flash_write_word(uint8_t sector, uint32_t offset, uint32_t data) { +secbool flash_write_word(uint16_t sector, uint32_t offset, uint32_t data) { if (offset % 4) { // we write only at 4-byte boundary return secfalse; } diff --git a/storage/tests/c/flash.h b/storage/tests/c/flash.h index 82508e477..674f3dba5 100644 --- a/storage/tests/c/flash.h +++ b/storage/tests/c/flash.h @@ -24,19 +24,15 @@ #include #include "secbool.h" -#define FLASH_SECTOR_COUNT 24 +#define FLASH_BYTE_ACCESS 1 -secbool __wur flash_unlock_write(void); -secbool __wur flash_lock_write(void); +#include "flash_common.h" +#include "test_layout.h" -const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size); +uint32_t flash_sector_size(uint16_t sector); -secbool __wur flash_erase_sectors(const uint8_t *sectors, int len, - void (*progress)(int pos, int len)); -static inline secbool flash_erase(uint8_t sector) { - return flash_erase_sectors(§or, 1, NULL); -} -secbool __wur flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data); -secbool __wur flash_write_word(uint8_t sector, uint32_t offset, uint32_t data); +secbool flash_write_byte(uint16_t sector, uint32_t offset, uint8_t data); + +secbool flash_write_word(uint16_t sector, uint32_t offset, uint32_t data); #endif diff --git a/storage/tests/c/norcow_config.h b/storage/tests/c/norcow_config.h index 1e28339b3..ea72a1115 100644 --- a/storage/tests/c/norcow_config.h +++ b/storage/tests/c/norcow_config.h @@ -24,8 +24,6 @@ #define NORCOW_SECTOR_COUNT 2 #define NORCOW_SECTOR_SIZE (64 * 1024) -#define NORCOW_SECTORS \ - { 4, 16 } /* * The length of the sector header in bytes. The header is preserved between diff --git a/storage/tests/c/test_layout.c b/storage/tests/c/test_layout.c new file mode 100644 index 000000000..2d23c38e9 --- /dev/null +++ b/storage/tests/c/test_layout.c @@ -0,0 +1,21 @@ + +#include "test_layout.h" + +const flash_area_t STORAGE_AREAS[STORAGE_AREAS_COUNT] = { + { + .num_subareas = 1, + .subarea[0] = + { + .first_sector = 4, + .num_sectors = 1, + }, + }, + { + .num_subareas = 1, + .subarea[0] = + { + .first_sector = 16, + .num_sectors = 1, + }, + }, +}; diff --git a/storage/tests/c/test_layout.h b/storage/tests/c/test_layout.h new file mode 100644 index 000000000..1223f198f --- /dev/null +++ b/storage/tests/c/test_layout.h @@ -0,0 +1,10 @@ +#ifndef TEST_LAYOUT_H +#define TEST_LAYOUT_H + +#define STORAGE_AREAS_COUNT 2 + +#include "flash_common.h" + +extern const flash_area_t STORAGE_AREAS[STORAGE_AREAS_COUNT]; + +#endif