refactor(core): move flash driver to sys layer
What changed, and why it matters
This commit is a pure code reorganization: it moves the flash memory driver files from one directory (embed/util/flash) to another (embed/sys/flash) and updates all include paths and build scripts accordingly. The actual flash programming, erasing, and one-time-programmable (OTP) logic is copied verbatim, with no functional changes. There is no indication this fixes or introduces a security vulnerability.
No security action required. Treat as routine refactoring. Standard regression/build testing is sufficient.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change is a directory refactor of the Trezor core flash driver. Files under core/embed/util/flash/ were relocated to core/embed/sys/flash/; headers changed from
Changed components
core/embed/sys/flash drivercore/embed/util/flash driver (removed)boardloaderbootloaderbootloader_ciprodtestsecmonunix emulatorRust trezorhal bindingsInspect captured patch +1563 / −1563
diff --git a/core/SConscript.boardloader b/core/SConscript.boardloader
index 2f5b34cf..77f96b73 100644
--- a/core/SConscript.boardloader
+++ b/core/SConscript.boardloader
@@ -93,13 +93,13 @@ SOURCE_MOD += [
'embed/gfx/gfx_draw.c',
'embed/gfx/terminal.c',
'embed/io/display/display_utils.c',
- 'embed/util/flash/flash_utils.c',
'embed/util/image/image.c',
'embed/util/rsod/rsod.c',
'embed/util/rsod/rsod_special.c',
'embed/rtl/error_handling.c',
'embed/rtl/scm_revision.c',
'embed/rtl/strutils.c',
+ 'embed/sys/flash/flash_utils.c',
]
if not PRODUCTION:
diff --git a/core/SConscript.bootloader b/core/SConscript.bootloader
index 0d357279..72562658 100644
--- a/core/SConscript.bootloader
+++ b/core/SConscript.bootloader
@@ -118,13 +118,13 @@ SOURCE_MOD += [
'embed/gfx/gfx_draw.c',
'embed/gfx/terminal.c',
'embed/io/display/display_utils.c',
- 'embed/util/flash/flash_utils.c',
'embed/util/image/image.c',
'embed/util/rsod/rsod.c',
'embed/util/rsod/rsod_special.c',
'embed/rtl/error_handling.c',
'embed/rtl/scm_revision.c',
'embed/rtl/strutils.c',
+ 'embed/sys/flash/flash_utils.c',
'vendor/micropython/lib/uzlib/adler32.c',
'vendor/micropython/lib/uzlib/crc32.c',
'vendor/micropython/lib/uzlib/tinflate.c',
diff --git a/core/SConscript.bootloader_ci b/core/SConscript.bootloader_ci
index 10716c7f..ebbd14b1 100644
--- a/core/SConscript.bootloader_ci
+++ b/core/SConscript.bootloader_ci
@@ -97,13 +97,13 @@ SOURCE_MOD += [
'embed/gfx/gfx_draw.c',
'embed/gfx/terminal.c',
'embed/io/display/display_utils.c',
- 'embed/util/flash/flash_utils.c',
'embed/util/image/image.c',
'embed/util/rsod/rsod.c',
'embed/util/rsod/rsod_special.c',
'embed/rtl/error_handling.c',
'embed/rtl/scm_revision.c',
'embed/rtl/strutils.c',
+ 'embed/sys/flash/flash_utils.c',
'vendor/micropython/lib/uzlib/adler32.c',
'vendor/micropython/lib/uzlib/crc32.c',
'vendor/micropython/lib/uzlib/tinflate.c',
diff --git a/core/SConscript.bootloader_emu b/core/SConscript.bootloader_emu
index abf06dcf..45dac359 100644
--- a/core/SConscript.bootloader_emu
+++ b/core/SConscript.bootloader_emu
@@ -92,13 +92,13 @@ SOURCE_MOD += [
'embed/gfx/gfx_draw.c',
'embed/gfx/terminal.c',
'embed/io/display/display_utils.c',
- 'embed/util/flash/flash_utils.c',
'embed/util/image/image.c',
'embed/util/rsod/rsod.c',
'embed/util/rsod/rsod_special.c',
'embed/rtl/error_handling.c',
'embed/rtl/scm_revision.c',
'embed/rtl/strutils.c',
+ 'embed/sys/flash/flash_utils.c',
'vendor/micropython/lib/uzlib/adler32.c',
'vendor/micropython/lib/uzlib/crc32.c',
'vendor/micropython/lib/uzlib/tinflate.c',
diff --git a/core/embed/projects/boardloader/main.c b/core/embed/projects/boardloader/main.c
index 020ac185..b93f8395 100644
--- a/core/embed/projects/boardloader/main.c
+++ b/core/embed/projects/boardloader/main.c
@@ -25,11 +25,11 @@
#include <sec/option_bytes.h>
#include <sec/secret.h>
#include <sys/bootutils.h>
+#include <sys/flash.h>
#include <sys/reset_flags.h>
#include <sys/rng.h>
#include <sys/system.h>
#include <sys/systick.h>
-#include <util/flash.h>
#include <util/rsod.h>
#ifdef USE_BOOT_UCB
diff --git a/core/embed/projects/boardloader/sd_update.c b/core/embed/projects/boardloader/sd_update.c
index a002b9cd..0c403cda 100644
--- a/core/embed/projects/boardloader/sd_update.c
+++ b/core/embed/projects/boardloader/sd_update.c
@@ -6,9 +6,9 @@
#include <io/display.h>
#include <sys/bootutils.h>
+#include <sys/flash.h>
+#include <sys/flash_utils.h>
#include <sys/systick.h>
-#include <util/flash.h>
-#include <util/flash_utils.h>
#include <util/image.h>
#include "memzero.h"
diff --git a/core/embed/projects/bootloader/emulator.c b/core/embed/projects/bootloader/emulator.c
index d9de1d3c..e53076df 100644
--- a/core/embed/projects/bootloader/emulator.c
+++ b/core/embed/projects/bootloader/emulator.c
@@ -8,9 +8,9 @@
#include <io/display.h>
#include <sys/bootargs.h>
#include <sys/bootutils.h>
+#include <sys/flash.h>
+#include <sys/flash_otp.h>
#include <sys/logging.h>
-#include <util/flash.h>
-#include <util/flash_otp.h>
#include "bootui.h"
#ifdef LOCKABLE_BOOTLOADER
diff --git a/core/embed/projects/bootloader/fw_check.c b/core/embed/projects/bootloader/fw_check.c
index e550da64..8e1fbef4 100644
--- a/core/embed/projects/bootloader/fw_check.c
+++ b/core/embed/projects/bootloader/fw_check.c
@@ -21,8 +21,8 @@
#include <trezor_rtl.h>
#include <sys/bootutils.h>
-#include <util/flash.h>
-#include <util/flash_otp.h>
+#include <sys/flash.h>
+#include <sys/flash_otp.h>
#include <util/image.h>
#include "fw_check.h"
diff --git a/core/embed/projects/bootloader/main.c b/core/embed/projects/bootloader/main.c
index 63388c05..be4c29de 100644
--- a/core/embed/projects/bootloader/main.c
+++ b/core/embed/projects/bootloader/main.c
@@ -29,10 +29,10 @@
#include <sec/unit_properties.h>
#include <sys/bootargs.h>
#include <sys/bootutils.h>
+#include <sys/flash_utils.h>
#include <sys/system.h>
#include <sys/systick.h>
#include <sys/types.h>
-#include <util/flash_utils.h>
#include <util/image.h>
#include <util/rsod.h>
#include <util/rsod_special.h>
diff --git a/core/embed/projects/bootloader/workflow/wf_empty_device.c b/core/embed/projects/bootloader/workflow/wf_empty_device.c
index 7d5704f6..f8871576 100644
--- a/core/embed/projects/bootloader/workflow/wf_empty_device.c
+++ b/core/embed/projects/bootloader/workflow/wf_empty_device.c
@@ -21,9 +21,9 @@
#include <trezor_rtl.h>
#include <io/notify.h>
+#include <sys/flash_utils.h>
#include <sys/systick.h>
#include <sys/types.h>
-#include <util/flash_utils.h>
#include <util/image.h>
#ifdef USE_STORAGE_HWKEY
diff --git a/core/embed/projects/bootloader/workflow/wf_firmware_update.c b/core/embed/projects/bootloader/workflow/wf_firmware_update.c
index 917e5010..fe3b2bb5 100644
--- a/core/embed/projects/bootloader/workflow/wf_firmware_update.c
+++ b/core/embed/projects/bootloader/workflow/wf_firmware_update.c
@@ -22,9 +22,9 @@
#include <sys/bootargs.h>
#include <sys/bootutils.h>
+#include <sys/flash.h>
+#include <sys/flash_utils.h>
#include <sys/systick.h>
-#include <util/flash.h>
-#include <util/flash_utils.h>
#include <util/rsod_special.h>
#if defined(LOCKABLE_BOOTLOADER) || USE_STORAGE_HWKEY
diff --git a/core/embed/projects/bootloader/workflow/wf_unlock_bootloader.c b/core/embed/projects/bootloader/workflow/wf_unlock_bootloader.c
index dba308be..fc7b68cd 100644
--- a/core/embed/projects/bootloader/workflow/wf_unlock_bootloader.c
+++ b/core/embed/projects/bootloader/workflow/wf_unlock_bootloader.c
@@ -21,7 +21,7 @@
#include <trezor_rtl.h>
#include <sec/secret.h>
-#include <util/flash_utils.h>
+#include <sys/flash_utils.h>
#ifdef USE_BACKUP_RAM
#include <sec/backup_ram.h>
diff --git a/core/embed/projects/bootloader/workflow/wf_wipe_device.c b/core/embed/projects/bootloader/workflow/wf_wipe_device.c
index d367d4ca..c635e18d 100644
--- a/core/embed/projects/bootloader/workflow/wf_wipe_device.c
+++ b/core/embed/projects/bootloader/workflow/wf_wipe_device.c
@@ -21,7 +21,7 @@
#include <trezor_rtl.h>
#include <io/notify.h>
-#include <util/flash_utils.h>
+#include <sys/flash_utils.h>
#ifdef USE_BLE
#include <io/ble.h>
diff --git a/core/embed/projects/bootloader_ci/main.c b/core/embed/projects/bootloader_ci/main.c
index 86621b62..e385d9c7 100644
--- a/core/embed/projects/bootloader_ci/main.c
+++ b/core/embed/projects/bootloader_ci/main.c
@@ -29,12 +29,12 @@
#include <sec/random_delays.h>
#include <sys/bootargs.h>
#include <sys/bootutils.h>
+#include <sys/flash_otp.h>
#include <sys/mpu.h>
#include <sys/rng.h>
#include <sys/sysevent.h>
#include <sys/system.h>
#include <sys/systick.h>
-#include <util/flash_otp.h>
#include <util/image.h>
#include <util/rsod.h>
diff --git a/core/embed/projects/bootloader_ci/messages.c b/core/embed/projects/bootloader_ci/messages.c
index e204cd6d..2eaad393 100644
--- a/core/embed/projects/bootloader_ci/messages.c
+++ b/core/embed/projects/bootloader_ci/messages.c
@@ -26,9 +26,9 @@
#include "pb/messages.pb.h"
#include <io/usb.h>
+#include <sys/flash.h>
+#include <sys/flash_utils.h>
#include <sys/sysevent.h>
-#include <util/flash.h>
-#include <util/flash_utils.h>
#include <util/image.h>
#include "version.h"
diff --git a/core/embed/projects/prodtest/cmd/prodtest_boardloader.c b/core/embed/projects/prodtest/cmd/prodtest_boardloader.c
index 7c13f139..087b1d82 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_boardloader.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_boardloader.c
@@ -21,8 +21,8 @@
#include <rtl/cli.h>
#include <sec/board_capabilities.h>
+#include <sys/flash.h>
#include <sys/mpu.h>
-#include <util/flash.h>
#include "common.h"
diff --git a/core/embed/projects/prodtest/cmd/prodtest_otp_batch.c b/core/embed/projects/prodtest/cmd/prodtest_otp_batch.c
index 190cd498..7a7f5314 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_otp_batch.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_otp_batch.c
@@ -21,7 +21,7 @@
#include <trezor_rtl.h>
#include <rtl/cli.h>
-#include <util/flash_otp.h>
+#include <sys/flash_otp.h>
static void prodtest_otp_read(cli_t* cli, uint8_t block_num) {
if (cli_arg_count(cli) > 0) {
diff --git a/core/embed/projects/prodtest/cmd/prodtest_otp_variant.c b/core/embed/projects/prodtest/cmd/prodtest_otp_variant.c
index 05053a98..d43e15d3 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_otp_variant.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_otp_variant.c
@@ -24,7 +24,7 @@
#include <rtl/cli.h>
#include <rtl/printf.h>
#include <sec/secret.h>
-#include <util/flash_otp.h>
+#include <sys/flash_otp.h>
#include <stdlib.h>
#include "prodtest_optiga.h"
diff --git a/core/embed/projects/prodtest/emulator.c b/core/embed/projects/prodtest/emulator.c
index bc9a0984..261812c4 100644
--- a/core/embed/projects/prodtest/emulator.c
+++ b/core/embed/projects/prodtest/emulator.c
@@ -8,8 +8,8 @@
#include <io/display.h>
#include <sec/secret.h>
-#include <util/flash.h>
-#include <util/flash_otp.h>
+#include <sys/flash.h>
+#include <sys/flash_otp.h>
int prodtest_main(void);
diff --git a/core/embed/projects/prodtest/main.c b/core/embed/projects/prodtest/main.c
index c6abb41f..7f1e9b4e 100644
--- a/core/embed/projects/prodtest/main.c
+++ b/core/embed/projects/prodtest/main.c
@@ -28,9 +28,9 @@
#include <rtl/cli.h>
#include <sec/board_capabilities.h>
#include <sec/unit_properties.h>
+#include <sys/flash_otp.h>
#include <sys/system.h>
#include <sys/systick.h>
-#include <util/flash_otp.h>
#include <util/rsod.h>
#include "commands.h"
diff --git a/core/embed/projects/secmon/main.c b/core/embed/projects/secmon/main.c
index a332aacd..82cc3151 100644
--- a/core/embed/projects/secmon/main.c
+++ b/core/embed/projects/secmon/main.c
@@ -26,11 +26,11 @@
#include <sec/secure_aes.h>
#include <sec/unit_properties.h>
#include <sys/bootutils.h>
+#include <sys/flash.h>
#include <sys/system.h>
#include <sys/systick.h>
#include <sys/sysutils.h>
#include <util/boot_image.h>
-#include <util/flash.h>
#ifdef USE_BACKUP_RAM
#include <sec/backup_ram.h>
diff --git a/core/embed/projects/unix/main.c b/core/embed/projects/unix/main.c
index 2d9c5cdd..7c013b23 100644
--- a/core/embed/projects/unix/main.c
+++ b/core/embed/projects/unix/main.c
@@ -40,10 +40,10 @@
#include <io/usb_config.h>
#include <sec/secret.h>
#include <sec/unit_properties.h>
+#include <sys/flash.h>
+#include <sys/flash_otp.h>
#include <sys/system.h>
#include <sys/systimer.h>
-#include <util/flash.h>
-#include <util/flash_otp.h>
#include <util/rsod.h>
#include "extmod/misc.h"
#include "extmod/vfs_posix.h"
diff --git a/core/embed/rust/build.rs b/core/embed/rust/build.rs
index 6074e65b..f0ce7dfb 100644
--- a/core/embed/rust/build.rs
+++ b/core/embed/rust/build.rs
@@ -53,7 +53,7 @@ const DEFAULT_BINDGEN_MACROS_COMMON: &[&str] = &[
"-I../sys/task/inc",
"-I../sys/suspend/inc",
"-I../sys/irq/inc",
- "-I../util/flash/inc",
+ "-I../sys/flash/inc",
"-I../util/translations/inc",
"-I../models",
"-DTREZOR_EMULATOR",
diff --git a/core/embed/rust/trezorhal.h b/core/embed/rust/trezorhal.h
index e92d37e3..a86eb92e 100644
--- a/core/embed/rust/trezorhal.h
+++ b/core/embed/rust/trezorhal.h
@@ -7,11 +7,11 @@
#include <io/display_utils.h>
#include <io/usb.h>
#include <rtl/secbool.h>
+#include <sys/flash.h>
#include <sys/irq.h>
#include <sys/logging.h>
#include <sys/sysevent.h>
#include <sys/systick.h>
-#include <util/flash.h>
#include <util/translations.h>
#include "rust_types.h"
diff --git a/core/embed/sec/monoctr/stm32f4/monoctr.c b/core/embed/sec/monoctr/stm32f4/monoctr.c
index e51a6bb4..cc9088a6 100644
--- a/core/embed/sec/monoctr/stm32f4/monoctr.c
+++ b/core/embed/sec/monoctr/stm32f4/monoctr.c
@@ -21,8 +21,8 @@
#include <trezor_rtl.h>
#include <sec/monoctr.h>
+#include <sys/flash_otp.h>
#include <sys/mpu.h>
-#include <util/flash_otp.h>
#ifdef KERNEL_MODE
diff --git a/core/embed/sec/monoctr/stm32u5/monoctr.c b/core/embed/sec/monoctr/stm32u5/monoctr.c
index 9edad6a3..bff3f7a1 100644
--- a/core/embed/sec/monoctr/stm32u5/monoctr.c
+++ b/core/embed/sec/monoctr/stm32u5/monoctr.c
@@ -23,8 +23,8 @@
#include <sec/monoctr.h>
#include <sec/secret.h>
+#include <sys/flash.h>
#include <sys/mpu.h>
-#include <util/flash.h>
static int32_t get_offset(monoctr_type_t type) {
switch (type) {
diff --git a/core/embed/sec/monoctr/unix/monoctr.c b/core/embed/sec/monoctr/unix/monoctr.c
index 455995cd..b874711e 100644
--- a/core/embed/sec/monoctr/unix/monoctr.c
+++ b/core/embed/sec/monoctr/unix/monoctr.c
@@ -21,7 +21,7 @@
#include <trezor_rtl.h>
#include <sec/monoctr.h>
-#include <util/flash_otp.h>
+#include <sys/flash_otp.h>
static int get_otp_block(monoctr_type_t type) {
switch (type) {
diff --git a/core/embed/sec/option_bytes/stm32f4/option_bytes.c b/core/embed/sec/option_bytes/stm32f4/option_bytes.c
index 43fcf432..7f8cb762 100644
--- a/core/embed/sec/option_bytes/stm32f4/option_bytes.c
+++ b/core/embed/sec/option_bytes/stm32f4/option_bytes.c
@@ -20,8 +20,8 @@
#include <trezor_bsp.h>
#include <sec/option_bytes.h>
+#include <sys/flash_otp.h>
#include <sys/mpu.h>
-#include <util/flash_otp.h>
#ifdef KERNEL_MODE
diff --git a/core/embed/sec/option_bytes/stm32u5/option_bytes.c b/core/embed/sec/option_bytes/stm32u5/option_bytes.c
index c4d53bb5..5e3da802 100644
--- a/core/embed/sec/option_bytes/stm32u5/option_bytes.c
+++ b/core/embed/sec/option_bytes/stm32u5/option_bytes.c
@@ -24,7 +24,7 @@
#ifdef SECURE_MODE
#include <sec/option_bytes.h>
-#include <util/flash.h>
+#include <sys/flash.h>
#pragma GCC optimize( \
"no-stack-protector") // applies to all functions in this file
diff --git a/core/embed/sec/secret/stm32f4/secret.c b/core/embed/sec/secret/stm32f4/secret.c
index b20d25fb..b9d7debe 100644
--- a/core/embed/sec/secret/stm32f4/secret.c
+++ b/core/embed/sec/secret/stm32f4/secret.c
@@ -21,9 +21,9 @@
#include <trezor_rtl.h>
#include <sec/secret.h>
+#include <sys/flash.h>
+#include <sys/flash_utils.h>
#include <sys/mpu.h>
-#include <util/flash.h>
-#include <util/flash_utils.h>
#include <util/rsod_special.h>
#ifdef KERNEL_MODE
diff --git a/core/embed/sec/secret/stm32f4/secret_keys.c b/core/embed/sec/secret/stm32f4/secret_keys.c
index 4ea4e5bc..53b75ff0 100644
--- a/core/embed/sec/secret/stm32f4/secret_keys.c
+++ b/core/embed/sec/secret/stm32f4/secret_keys.c
@@ -28,8 +28,8 @@
#include "../secret_keys_common.h"
#include <sec/rng_strong.h>
+#include <sys/flash_otp.h>
#include <sys/mpu.h>
-#include <util/flash_otp.h>
#include "memzero.h"
#ifdef USE_OPTIGA
diff --git a/core/embed/sec/secret/stm32u5/secret.c b/core/embed/sec/secret/stm32u5/secret.c
index 6f52d873..a8445621 100644
--- a/core/embed/sec/secret/stm32u5/secret.c
+++ b/core/embed/sec/secret/stm32u5/secret.c
@@ -24,10 +24,10 @@
#include <sec/secret.h>
#include <sec/secure_aes.h>
#include <sys/bootutils.h>
+#include <sys/flash.h>
+#include <sys/flash_utils.h>
#include <sys/mpu.h>
#include <sys/rng.h>
-#include <util/flash.h>
-#include <util/flash_utils.h>
#include <util/rsod_special.h>
#include "memzero.h"
diff --git a/core/embed/sec/secret/stm32u5/secret_keys.c b/core/embed/sec/secret/stm32u5/secret_keys.c
index 9e0d46cb..b34a4b1c 100644
--- a/core/embed/sec/secret/stm32u5/secret_keys.c
+++ b/core/embed/sec/secret/stm32u5/secret_keys.c
@@ -158,8 +158,8 @@ secbool secret_key_storage_salt(uint16_t fw_type,
#else // SECRET_PRIVILEGED_MASTER_KEY_SLOT
#include <sec/rng_strong.h>
+#include <sys/flash_otp.h>
#include <sys/mpu.h>
-#include <util/flash_otp.h>
#ifdef USE_OPTIGA
secbool secret_key_optiga_pairing(uint8_t dest[OPTIGA_PAIRING_SECRET_SIZE]) {
diff --git a/core/embed/sec/storage/stm32f4/storage_salt.c b/core/embed/sec/storage/stm32f4/storage_salt.c
index 3ade5bb9..aa10f4c6 100644
--- a/core/embed/sec/storage/stm32f4/storage_salt.c
+++ b/core/embed/sec/storage/stm32f4/storage_salt.c
@@ -22,9 +22,9 @@
#include <trezor_model.h>
#include <trezor_rtl.h>
+#include <sys/flash_otp.h>
#include <sys/mpu.h>
#include <sys/rng.h>
-#include <util/flash_otp.h>
#include "stm32f4xx_ll_utils.h"
diff --git a/core/embed/sec/storage/stm32u5/storage_salt.c b/core/embed/sec/storage/stm32u5/storage_salt.c
index b19219f8..1c3b1f44 100644
--- a/core/embed/sec/storage/stm32u5/storage_salt.c
+++ b/core/embed/sec/storage/stm32u5/storage_salt.c
@@ -23,9 +23,9 @@
#include <trezor_rtl.h>
#include <sec/secret_keys.h>
+#include <sys/flash_otp.h>
#include <sys/mpu.h>
#include <sys/rng.h>
-#include <util/flash_otp.h>
#include <util/image.h>
#include "stm32u5xx_ll_utils.h"
diff --git a/core/embed/sec/unit_properties/stm32/unit_properties.c b/core/embed/sec/unit_properties/stm32/unit_properties.c
index 617ecd06..dbc717df 100644
--- a/core/embed/sec/unit_properties/stm32/unit_properties.c
+++ b/core/embed/sec/unit_properties/stm32/unit_properties.c
@@ -25,7 +25,7 @@
#include <trezor_model.h>
#include <trezor_rtl.h>
-#include <util/flash_otp.h>
+#include <sys/flash_otp.h>
// Unit properties driver structure
typedef struct {
diff --git a/core/embed/sec/unit_properties/unix/unit_properties.c b/core/embed/sec/unit_properties/unix/unit_properties.c
index 22ce5ce3..637f8833 100644
--- a/core/embed/sec/unit_properties/unix/unit_properties.c
+++ b/core/embed/sec/unit_properties/unix/unit_properties.c
@@ -21,7 +21,7 @@
#include <trezor_rtl.h>
#include <sec/unit_properties.h>
-#include <util/flash_otp.h>
+#include <sys/flash_otp.h>
// Unit properties driver structure
typedef struct {
diff --git a/core/embed/sys/flash/flash_utils.c b/core/embed/sys/flash/flash_utils.c
new file mode 100644
index 00000000..928bafd8
--- /dev/null
+++ b/core/embed/sys/flash/flash_utils.c
@@ -0,0 +1,103 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <trezor_model.h>
+#include <trezor_rtl.h>
+
+#include <sys/flash.h>
+#include <sys/flash_utils.h>
+#include <sys/mpu.h>
+
+typedef struct {
+ const flash_area_t* area;
+ mpu_mode_t mpu_mode;
+} flash_area_ref_t;
+
+// Erases the given list of flash areas.
+//
+// Invokes the progress_cb after each erased sector or page.
+static secbool erase_areas(const flash_area_ref_t* areas, int area_count,
+ flash_progress_callback_t progress_cb) {
+ int total = 0;
+ int progress = 0;
+
+ for (int i = 0; i < area_count; i++) {
+ total += flash_area_get_size(areas[i].area);
+ }
+
+ mpu_mode_t mpu_mode = mpu_get_mode();
+
+ for (int i = 0; i < area_count; i++) {
+ const flash_area_t* area = areas[i].area;
+ uint32_t offset = 0;
+ uint32_t bytes_erased = 0;
+
+ mpu_reconfig(areas[i].mpu_mode);
+
+ do {
+ if (progress_cb) {
+ progress_cb(progress, total);
+ }
+
+ if (sectrue != flash_area_erase_partial(area, offset, &bytes_erased)) {
+ mpu_restore(mpu_mode);
+ return secfalse;
+ }
+
+ offset += bytes_erased;
+ progress += bytes_erased;
+
+ } while (bytes_erased > 0);
+ }
+
+ mpu_restore(mpu_mode);
+ return sectrue;
+}
+
+secbool erase_storage(flash_progress_callback_t progress_cb) {
+ _Static_assert(STORAGE_AREAS_COUNT == 2,
+ "Unsupported number of storage areas");
+
+ static const flash_area_ref_t areas[] = {
+ {.area = &STORAGE_AREAS[0], .mpu_mode = MPU_MODE_STORAGE},
+ {.area = &STORAGE_AREAS[1], .mpu_mode = MPU_MODE_STORAGE},
+ };
+
+ return erase_areas(areas, ARRAY_LENGTH(areas), progress_cb);
+}
+
+secbool erase_device(flash_progress_callback_t progress_cb) {
+ _Static_assert(STORAGE_AREAS_COUNT == 2,
+ "Unsupported number of storage areas");
+
+ static const flash_area_ref_t areas[] = {
+ {.area = &STORAGE_AREAS[0], .mpu_mode = MPU_MODE_STORAGE},
+ {.area = &STORAGE_AREAS[1], .mpu_mode = MPU_MODE_STORAGE},
+ {.area = &ASSETS_AREA, .mpu_mode = MPU_MODE_ASSETS},
+#if defined(BOARDLOADER) || defined(BOOTLOADER)
+ {.area = &FIRMWARE_AREA, .mpu_mode = MPU_MODE_DEFAULT},
+#endif
+#if defined(BOARDLOADER) && defined(USE_SD_CARD)
+ {.area = &BOOTLOADER_AREA, .mpu_mode = MPU_MODE_DEFAULT},
+ {.area = &UNUSED_AREA, .mpu_mode = MPU_MODE_UNUSED_FLASH},
+#endif
+ };
+
+ return erase_areas(areas, ARRAY_LENGTH(areas), progress_cb);
+}
diff --git a/core/embed/sys/flash/inc/norcow_config.h b/core/embed/sys/flash/inc/norcow_config.h
new file mode 100644
index 00000000..6a9a2624
--- /dev/null
+++ b/core/embed/sys/flash/inc/norcow_config.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __NORCOW_CONFIG_H__
+#define __NORCOW_CONFIG_H__
+
+#include <trezor_model.h>
+#include <trezor_types.h>
+
+#include <sys/flash.h>
+
+#define NORCOW_HEADER_LEN 0
+#define NORCOW_SECTOR_COUNT 2
+
+#define STORAGE_AREAS_COUNT NORCOW_SECTOR_COUNT
+extern const flash_area_t STORAGE_AREAS[STORAGE_AREAS_COUNT];
+
+/*
+ * Current storage version.
+ */
+#define NORCOW_VERSION ((uint32_t)0x00000006)
+
+#endif
diff --git a/core/embed/sys/flash/inc/sys/flash.h b/core/embed/sys/flash/inc/sys/flash.h
new file mode 100644
index 00000000..43d22f18
--- /dev/null
+++ b/core/embed/sys/flash/inc/sys/flash.h
@@ -0,0 +1,54 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#ifdef KERNEL_MODE
+
+#include <trezor_types.h>
+
+#include <trezor-storage/flash_area.h>
+#include <trezor-storage/flash_ll.h>
+
+#include "../norcow_config.h"
+
+void flash_init(void);
+
+extern const flash_area_t BOARDLOADER_AREA;
+extern const flash_area_t SECRET_AREA;
+extern const flash_area_t BHK_AREA;
+extern const flash_area_t ASSETS_AREA;
+extern const flash_area_t BOOTLOADER_AREA;
+extern const flash_area_t UNUSED_AREA;
+
+#ifdef SECMON
+extern flash_area_t FIRMWARE_AREA;
+#else
+extern const flash_area_t FIRMWARE_AREA;
+#endif
+
+#ifdef USE_BOOT_UCB
+extern const flash_area_t BOOTUCB_AREA;
+extern const flash_area_t BOOTUPDATE_AREA;
+#ifdef BOARDLOADER
+extern const flash_area_t NONBOARDLOADER_AREA;
+#endif
+#endif // USE_BOOT_UCB
+
+#endif // KERNEL_MODE
diff --git a/core/embed/sys/flash/inc/sys/flash_otp.h b/core/embed/sys/flash/inc/sys/flash_otp.h
new file mode 100644
index 00000000..4996916c
--- /dev/null
+++ b/core/embed/sys/flash/inc/sys/flash_otp.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <trezor_types.h>
+
+#ifdef SECURE_MODE
+
+#define FLASH_OTP_NUM_BLOCKS 16
+#define FLASH_OTP_BLOCK_SIZE 32
+
+void flash_otp_init(void);
+
+secbool __wur flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data,
+ uint8_t datalen);
+secbool __wur flash_otp_write(uint8_t block, uint8_t offset,
+ const uint8_t *data, uint8_t datalen);
+secbool __wur flash_otp_lock(uint8_t block);
+secbool __wur flash_otp_is_locked(uint8_t block);
+
+#endif // SECURE_MODE
diff --git a/core/embed/sys/flash/inc/sys/flash_utils.h b/core/embed/sys/flash/inc/sys/flash_utils.h
new file mode 100644
index 00000000..bd973fb9
--- /dev/null
+++ b/core/embed/sys/flash/inc/sys/flash_utils.h
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef LIB_FLASH_UTILS_H
+#define LIB_FLASH_UTILS_H
+
+#include <trezor_types.h>
+
+#ifdef KERNEL_MODE
+
+// Progress callback function called during the flash erase operation.
+//
+// Progress is reported as: (100 * pos) / total [%].
+typedef void (*flash_progress_callback_t)(int pos, int total);
+
+// Erases both storage areas
+//
+// Callback is invoked after each sector or page is erased.
+secbool erase_storage(flash_progress_callback_t progress_cb);
+
+// Erases all flash areas including storage, assets and firmware.
+//
+// If called from boardloader, also erases bootloader area.
+//
+// Callback is invoked after each sector or page is erased.
+secbool erase_device(flash_progress_callback_t progress_cb);
+
+#endif // KERNEL_MODE
+
+#endif // LIB_FLASH_UTILS_H
diff --git a/core/embed/sys/flash/layout_helpers.h b/core/embed/sys/flash/layout_helpers.h
new file mode 100644
index 00000000..7d27ffcf
--- /dev/null
+++ b/core/embed/sys/flash/layout_helpers.h
@@ -0,0 +1,90 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#ifdef TREZOR_EMULATOR
+#define ENSURE_SECTOR_AT(addr, sector, access)
+#else
+// Static assertions ensuring that the flash address coresponds
+// to the expected sector start. This macro is used in the
+// definitions below.
+#define ENSURE_SECTOR_AT(addr, sector, access) \
+ _Static_assert(FLASH_SECTOR_TO_ADDR(EVAL(sector), access) == EVAL(addr), \
+ "Sector address mismatch")
+#endif
+
+#define ACCESS_DEFAULT 0
+#define ACCESS_NONSECURE 1
+
+// Helper that expands to its argument
+#define EVAL(x) x
+
+// Defines flash_subarea_t structure
+#define SUBAREA(_first_sector, _end_sectors) \
+ { \
+ .first_sector = (_first_sector), \
+ .num_sectors = (_end_sectors) - (_first_sector) + 1, \
+ }
+
+// Defines flash area containing 1 subarea
+#define DEFINE_SINGLE_AREA(id, prefix, access) \
+ ENSURE_SECTOR_AT(prefix##_START, prefix##_SECTOR_START, access); \
+ ENSURE_SECTOR_AT(prefix##_START + prefix##_MAXSIZE, prefix##_SECTOR_END + 1, \
+ access); \
+ const flash_area_t prefix##_AREA = { \
+ .num_subareas = 1, \
+ .subarea[0] = SUBAREA(prefix##_SECTOR_START, prefix##_SECTOR_END), \
+ }
+
+// Defines flash area containing two subareas from two
+// different blocks giveng by their prefixes
+#define DEFINE_SPLIT2_AREA(id, prefix1, access1, prefix2, access2) \
+ ENSURE_SECTOR_AT(prefix1##_START, prefix1##_SECTOR_START, access1); \
+ ENSURE_SECTOR_AT(prefix1##_START + prefix1##_MAXSIZE, \
+ prefix1##_SECTOR_END + 1, access1); \
+ ENSURE_SECTOR_AT(prefix2##_START, prefix2##_SECTOR_START, access2); \
+ ENSURE_SECTOR_AT(prefix2##_START + prefix2##_MAXSIZE, \
+ prefix2##_SECTOR_END + 1, access2); \
+ const flash_area_t id = { \
+ .num_subareas = 2, \
+ .subarea[0] = SUBAREA(prefix1##_SECTOR_START, prefix1##_SECTOR_END), \
+ .subarea[1] = SUBAREA(prefix2##_SECTOR_START, prefix2##_SECTOR_END), \
+ }
+
+// Defines array of two flash areas from two differenc blocks
+// given by their prefixes
+#define DEFINE_ARRAY2_AREA(id, prefix1, prefix2, access) \
+ ENSURE_SECTOR_AT(prefix1##_START, prefix1##_SECTOR_START, access); \
+ ENSURE_SECTOR_AT(prefix1##_START + prefix1##_MAXSIZE, \
+ prefix1##_SECTOR_END + 1, access); \
+ ENSURE_SECTOR_AT(prefix2##_START, prefix2##_SECTOR_START, access); \
+ ENSURE_SECTOR_AT(prefix2##_START + prefix2##_MAXSIZE, \
+ prefix2##_SECTOR_END + 1, access); \
+ const flash_area_t id[] = { \
+ { \
+ .num_subareas = 1, \
+ .subarea[0] = SUBAREA(prefix1##_SECTOR_START, prefix1##_SECTOR_END), \
+ }, \
+ { \
+ .num_subareas = 1, \
+ .subarea[0] = SUBAREA(prefix2##_SECTOR_START, prefix2##_SECTOR_END), \
+ }}
+
+#define DEFINE_EMPTY_AREA(id) const flash_area_t id = {.num_subareas = 0}
diff --git a/core/embed/sys/flash/stm32f4/flash.c b/core/embed/sys/flash/stm32f4/flash.c
new file mode 100644
index 00000000..73a3d681
--- /dev/null
+++ b/core/embed/sys/flash/stm32f4/flash.c
@@ -0,0 +1,202 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <trezor_bsp.h>
+#include <trezor_rtl.h>
+
+#include <sys/flash.h>
+
+#ifdef KERNEL_MODE
+
+#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] = {
+ [0] = 0x08000000, // - 0x08003FFF | 16 KiB
+ [1] = 0x08004000, // - 0x08007FFF | 16 KiB
+ [2] = 0x08008000, // - 0x0800BFFF | 16 KiB
+ [3] = 0x0800C000, // - 0x0800FFFF | 16 KiB
+ [4] = 0x08010000, // - 0x0801FFFF | 64 KiB
+ [5] = 0x08020000, // - 0x0803FFFF | 128 KiB
+ [6] = 0x08040000, // - 0x0805FFFF | 128 KiB
+ [7] = 0x08060000, // - 0x0807FFFF | 128 KiB
+ [8] = 0x08080000, // - 0x0809FFFF | 128 KiB
+ [9] = 0x080A0000, // - 0x080BFFFF | 128 KiB
+ [10] = 0x080C0000, // - 0x080DFFFF | 128 KiB
+ [11] = 0x080E0000, // - 0x080FFFFF | 128 KiB
+#if defined STM32F427xx || defined STM32F429xx
+ [12] = 0x08100000, // - 0x08103FFF | 16 KiB
+ [13] = 0x08104000, // - 0x08107FFF | 16 KiB
+ [14] = 0x08108000, // - 0x0810BFFF | 16 KiB
+ [15] = 0x0810C000, // - 0x0810FFFF | 16 KiB
+ [16] = 0x08110000, // - 0x0811FFFF | 64 KiB
+ [17] = 0x08120000, // - 0x0813FFFF | 128 KiB
+ [18] = 0x08140000, // - 0x0815FFFF | 128 KiB
+ [19] = 0x08160000, // - 0x0817FFFF | 128 KiB
+ [20] = 0x08180000, // - 0x0819FFFF | 128 KiB
+ [21] = 0x081A0000, // - 0x081BFFFF | 128 KiB
+ [22] = 0x081C0000, // - 0x081DFFFF | 128 KiB
+ [23] = 0x081E0000, // - 0x081FFFFF | 128 KiB
+ [24] = 0x08200000, // last element - not a valid sector
+#elif defined STM32F405xx
+ [12] = 0x08100000, // last element - not a valid sector
+#else
+#error Unknown MCU
+#endif
+};
+
+const void *flash_get_address(uint16_t sector, uint32_t offset, uint32_t size) {
+ if (sector >= FLASH_SECTOR_COUNT) {
+ return NULL;
+ }
+ const uint32_t addr = FLASH_SECTOR_TABLE[sector] + offset;
+ const uint32_t next = FLASH_SECTOR_TABLE[sector + 1];
+ if (addr + size > next) {
+ return NULL;
+ }
+ return (const void *)addr;
+}
+
+uint32_t flash_sector_size(uint16_t first_sector, uint16_t sector_count) {
+ if (first_sector + sector_count > FLASH_SECTOR_COUNT) {
+ return 0;
+ }
+ return FLASH_SECTOR_TABLE[first_sector + sector_count] -
+ FLASH_SECTOR_TABLE[first_sector];
+}
+
+uint16_t flash_sector_find(uint16_t first_sector, uint32_t offset) {
+ uint16_t sector = first_sector;
+
+ while (sector < FLASH_SECTOR_COUNT) {
+ uint32_t sector_size =
+ FLASH_SECTOR_TABLE[sector + 1] - FLASH_SECTOR_TABLE[sector];
+
+ if (offset < sector_size) {
+ break;
+ }
+ offset -= sector_size;
+ sector++;
+ }
+
+ return sector;
+}
+
+secbool flash_unlock_write(void) {
+ HAL_FLASH_Unlock();
+ FLASH->SR |= FLASH_STATUS_ALL_FLAGS; // clear all status flags
+ return sectrue;
+}
+
+secbool flash_lock_write(void) {
+ HAL_FLASH_Lock();
+ return sectrue;
+}
+
+secbool flash_sector_erase(uint16_t sector) {
+ if (sector >= FLASH_SECTOR_COUNT) {
+ return secfalse;
+ }
+
+ FLASH_EraseInitTypeDef EraseInitStruct = {
+ .TypeErase = FLASH_TYPEERASE_SECTORS,
+ .VoltageRange = FLASH_VOLTAGE_RANGE_3,
+ .Sector = sector,
+ .NbSectors = 1,
+ };
+
+ uint32_t sector_error;
+
+ if (HAL_FLASHEx_Erase(&EraseInitStruct, §or_error) != HAL_OK) {
+ return secfalse;
+ }
+
+ // check whether the sector was really deleted (contains only 0xFF)
+ uint32_t addr_start = FLASH_SECTOR_TABLE[sector];
+ uint32_t addr_end = FLASH_SECTOR_TABLE[sector + 1];
+
+ for (uint32_t addr = addr_start; addr < addr_end; addr += 4) {
+ if (*((const uint32_t *)addr) != 0xFFFFFFFF) {
+ return secfalse;
+ }
+ }
+
+ return sectrue;
+}
+
+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;
+ }
+ if (data != (data & *((const uint8_t *)address))) {
+ return secfalse;
+ }
+ if (HAL_OK != HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, address, data)) {
+ return secfalse;
+ }
+ if (data != *((const uint8_t *)address)) {
+ return secfalse;
+ }
+ return sectrue;
+}
+
+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;
+ }
+ if (offset % sizeof(uint32_t)) { // we write only at 4-byte boundary
+ return secfalse;
+ }
+ if (data != (data & *((const uint32_t *)address))) {
+ return secfalse;
+ }
+ if (HAL_OK != HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, data)) {
+ return secfalse;
+ }
+ if (data != *((const uint32_t *)address)) {
+ 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]);
+}
+
+#endif // KERNEL_MODE
diff --git a/core/embed/sys/flash/stm32f4/flash_layout.c b/core/embed/sys/flash/stm32f4/flash_layout.c
new file mode 100644
index 00000000..aee17776
--- /dev/null
+++ b/core/embed/sys/flash/stm32f4/flash_layout.c
@@ -0,0 +1,56 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef KERNEL_MODE
+
+#include <trezor_bsp.h>
+#include <trezor_model.h>
+
+#include <sys/flash.h>
+
+#include "../layout_helpers.h"
+
+// Convert sector number to address
+//
+// This conversion is used in static assert in definitions below
+#define FLASH_SECTOR_TO_ADDR(sector, nonsecure) \
+ (FLASH_BASE + ((sector) / 12) * 0x100000 + \
+ (((sector) % 12) < 4 \
+ ? ((sector) % 12) * 0x4000 \
+ : (((sector) % 12) < 5 ? 0x10000 : ((sector) % 12 - 4) * 0x20000)))
+
+// Define all flash areas as `const flash_area_t ID = { .. };`
+
+DEFINE_ARRAY2_AREA(STORAGE_AREAS, STORAGE_1, STORAGE_2, ACCESS_DEFAULT);
+DEFINE_SINGLE_AREA(BOARDLOADER_AREA, BOARDLOADER, ACCESS_DEFAULT);
+DEFINE_SINGLE_AREA(BOOTLOADER_AREA, BOOTLOADER, ACCESS_DEFAULT);
+DEFINE_SPLIT2_AREA(FIRMWARE_AREA, FIRMWARE_P1, ACCESS_DEFAULT, FIRMWARE_P2,
+ ACCESS_DEFAULT);
+
+#ifdef SECRET_SECTOR_START
+DEFINE_SINGLE_AREA(SECRET_AREA, SECRET, ACCESS_DEFAULT);
+#else
+DEFINE_EMPTY_AREA(SECRET_AREA);
+#endif
+
+DEFINE_SINGLE_AREA(ASSETS_AREA, ASSETS, ACCESS_DEFAULT);
+DEFINE_SPLIT2_AREA(UNUSED_AREA, UNUSED_1, ACCESS_DEFAULT, UNUSED_2,
+ ACCESS_DEFAULT);
+
+#endif // KERNEL_MODE
diff --git a/core/embed/sys/flash/stm32f4/flash_otp.c b/core/embed/sys/flash/stm32f4/flash_otp.c
new file mode 100644
index 00000000..444583be
--- /dev/null
+++ b/core/embed/sys/flash/stm32f4/flash_otp.c
@@ -0,0 +1,108 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <trezor_bsp.h>
+#include <trezor_rtl.h>
+
+#include <sys/flash.h>
+#include <sys/flash_otp.h>
+#include <sys/mpu.h>
+
+#ifdef KERNEL_MODE
+
+#define FLASH_OTP_LOCK_BASE 0x1FFF7A00U
+
+void flash_otp_init() {
+ // intentionally left empty
+}
+
+secbool flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data,
+ uint8_t datalen) {
+ if (block >= FLASH_OTP_NUM_BLOCKS ||
+ offset + datalen > FLASH_OTP_BLOCK_SIZE) {
+ return secfalse;
+ }
+
+ mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP);
+
+ for (uint8_t i = 0; i < datalen; i++) {
+ data[i] = *(__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE +
+ offset + i);
+ }
+
+ mpu_restore(mpu_mode);
+
+ return sectrue;
+}
+
+secbool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data,
+ uint8_t datalen) {
+ if (block >= FLASH_OTP_NUM_BLOCKS ||
+ offset + datalen > FLASH_OTP_BLOCK_SIZE) {
+ return secfalse;
+ }
+
+ mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP);
+
+ ensure(flash_unlock_write(), NULL);
+ for (uint8_t i = 0; i < datalen; i++) {
+ uint32_t address =
+ FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE + offset + i;
+ ensure(sectrue * (HAL_OK == HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE,
+ address, data[i])),
+ NULL);
+ }
+ ensure(flash_lock_write(), NULL);
+
+ mpu_restore(mpu_mode);
+
+ return sectrue;
+}
+
+secbool flash_otp_lock(uint8_t block) {
+ if (block >= FLASH_OTP_NUM_BLOCKS) {
+ return secfalse;
+ }
+
+ mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP);
+
+ ensure(flash_unlock_write(), NULL);
+ HAL_StatusTypeDef ret = HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE,
+ FLASH_OTP_LOCK_BASE + block, 0x00);
+ ensure(flash_lock_write(), NULL);
+
+ mpu_restore(mpu_mode);
+
+ return sectrue * (ret == HAL_OK);
+}
+
+secbool flash_otp_is_locked(uint8_t block) {
+ secbool is_locked;
+
+ mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP);
+
+ is_locked =
+ sectrue * (0x00 == *(__IO uint8_t *)(FLASH_OTP_LOCK_BASE + block));
+
+ mpu_restore(mpu_mode);
+
+ return is_locked;
+}
+
+#endif // KERNEL_MODE
diff --git a/core/embed/sys/flash/stm32u5/flash.c b/core/embed/sys/flash/stm32u5/flash.c
new file mode 100644
index 00000000..9ee27547
--- /dev/null
+++ b/core/embed/sys/flash/stm32u5/flash.c
@@ -0,0 +1,258 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <trezor_bsp.h>
+#include <trezor_model.h>
+#include <trezor_rtl.h>
+
+#include <sys/flash.h>
+
+#ifdef KERNEL_MODE
+
+#ifdef STM32U585xx
+#define FLASH_BANK_PAGES 128
+#define FLASH_SECTOR_COUNT (FLASH_BANK_PAGES * 2)
+#else
+#define FLASH_BANK_PAGES 256
+#define FLASH_SECTOR_COUNT (FLASH_BANK_PAGES * 2)
+#endif
+
+#define FLASH_STATUS_ALL_FLAGS \
+ (FLASH_NSSR_PGSERR | FLASH_NSSR_PGAERR | FLASH_NSSR_WRPERR | FLASH_NSSR_EOP)
+
+#ifdef SECMON
+extern uint32_t _codelen;
+#define SECMON_SIZE ((uint32_t) & _codelen)
+#define KERNEL_SECTOR_START \
+ ((FIRMWARE_START_S + SECMON_SIZE - FLASH_BASE) / FLASH_PAGE_SIZE)
+
+flash_area_t FIRMWARE_AREA = {0};
+#endif // SECMON
+
+void flash_init(void) {
+#ifdef SECMON
+ // FIRMWARE_AREA is defined here because it depends on the
+ // SECMON size which is not known at compile time.
+
+ FIRMWARE_AREA = (flash_area_t){
+ .num_subareas = 2,
+ .subarea[0] =
+ {
+ .first_sector = FIRMWARE_SECTOR_START,
+ .num_sectors = KERNEL_SECTOR_START - FIRMWARE_SECTOR_START,
+ },
+ .subarea[1] =
+ {
+ .first_sector = KERNEL_SECTOR_START,
+ .num_sectors = FIRMWARE_SECTOR_END - KERNEL_SECTOR_START + 1,
+ },
+ };
+#endif
+}
+
+static bool flash_sector_is_secure(uint32_t sector) {
+#if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+#ifdef SECMON
+ if (sector < KERNEL_SECTOR_START) {
+ return true;
+ } else if (sector >= STORAGE_1_SECTOR_START &&
+ sector <= STORAGE_1_SECTOR_END) {
+ return true;
+ } else if (sector >= STORAGE_2_SECTOR_START &&
+ sector <= STORAGE_2_SECTOR_END) {
+ return true;
+ }
+#else
+ return true;
+#endif
+#endif
+ return false;
+}
+
+const void *flash_get_address(uint16_t sector, uint32_t offset, uint32_t size) {
+ if (sector >= FLASH_SECTOR_COUNT) {
+ return NULL;
+ }
+
+ if (offset + size > FLASH_PAGE_SIZE) {
+ return NULL;
+ }
+
+ uint32_t base_addr =
+ flash_sector_is_secure(sector) ? FLASH_BASE_S : FLASH_BASE_NS;
+
+ return (const void *)(base_addr + FLASH_PAGE_SIZE * sector + offset);
+}
+
+uint32_t flash_sector_size(uint16_t first_sector, uint16_t sector_count) {
+ if (first_sector + sector_count > FLASH_SECTOR_COUNT) {
+ return 0;
+ }
+ return FLASH_PAGE_SIZE * sector_count;
+}
+
+uint16_t flash_sector_find(uint16_t first_sector, uint32_t offset) {
+ return first_sector + offset / FLASH_PAGE_SIZE;
+}
+
+secbool flash_unlock_write(void) {
+ HAL_FLASH_Unlock();
+ FLASH->NSSR |= FLASH_STATUS_ALL_FLAGS; // clear all status flags
+#if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+ FLASH->SECSR |= FLASH_STATUS_ALL_FLAGS; // clear all status flags
+#endif
+ return sectrue;
+}
+
+secbool flash_lock_write(void) {
+ HAL_FLASH_Lock();
+ return sectrue;
+}
+
+secbool flash_sector_erase(uint16_t sector) {
+ if (sector >= FLASH_SECTOR_COUNT) {
+ return secfalse;
+ }
+
+ FLASH_EraseInitTypeDef EraseInitStruct = {
+ .TypeErase = FLASH_TYPEERASE_PAGES,
+ .Banks = FLASH_BANK_1,
+ .Page = sector,
+ .NbPages = 1,
+ };
+
+ if (sector >= FLASH_BANK_PAGES) {
+ EraseInitStruct.Banks = FLASH_BANK_2;
+ EraseInitStruct.Page = sector - FLASH_BANK_PAGES;
+ }
+
+ if (flash_sector_is_secure(sector)) {
+ EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
+ }
+
+ uint32_t sector_error = 0;
+
+ if (HAL_FLASHEx_Erase(&EraseInitStruct, §or_error) != HAL_OK) {
+ return secfalse;
+ }
+
+ // check whether the sector was really deleted (contains only 0xFF)
+ const uint32_t *sector_start =
+ (const uint32_t *)flash_get_address(sector, 0, 0);
+
+ const uint32_t *sector_end =
+ sector_start + flash_sector_size(sector, 1) / sizeof(uint32_t);
+
+ for (const uint32_t *addr = sector_start; addr < sector_end; addr++) {
+ if (*addr != 0xFFFFFFFF) {
+ return secfalse;
+ }
+ }
+
+ return sectrue;
+}
+
+secbool flash_write_quadword(uint16_t sector, uint32_t offset,
+ const uint32_t *data) {
+ uint32_t address =
+ (uint32_t)flash_get_address(sector, offset, FLASH_QUADWORD_SIZE);
+ if (address == 0) {
+ return secfalse;
+ }
+ if (offset % FLASH_QUADWORD_SIZE) { // we write only at 16-byte boundary
+ return secfalse;
+ }
+
+ 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 < FLASH_QUADWORD_WORDS; i++) {
+ if (data[i] != *((const uint32_t *)address + i)) {
+ all_match = secfalse;
+ break;
+ }
+ }
+ if (all_match == sectrue) {
+ return sectrue;
+ }
+
+ if (HAL_OK !=
+ HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, address, (uint32_t)data)) {
+ return secfalse;
+ }
+
+ for (int i = 0; i < FLASH_QUADWORD_WORDS; i++) {
+ if (data[i] != *((const uint32_t *)address + i)) {
+ return secfalse;
+ }
+ }
+ return sectrue;
+}
+
+secbool flash_write_burst(uint16_t sector, uint32_t offset,
+ const uint32_t *data) {
+ uint32_t address =
+ (uint32_t)flash_get_address(sector, offset, FLASH_BURST_SIZE);
+ if (address == 0) {
+ return secfalse;
+ }
+ if (offset % FLASH_BURST_SIZE) { // we write only at 128-byte boundary
+ return secfalse;
+ }
+
+ for (int i = 0; i < FLASH_BURST_WORDS; i++) {
+ if (data[i] != (data[i] & *((const uint32_t *)address + i))) {
+ return secfalse;
+ }
+ }
+
+ secbool all_match = sectrue;
+ for (int i = 0; i < FLASH_BURST_WORDS; i++) {
+ if (data[i] != *((const uint32_t *)address + i)) {
+ all_match = secfalse;
+ break;
+ }
+ }
+ if (all_match == sectrue) {
+ return sectrue;
+ }
+
+ if (HAL_OK !=
+ HAL_FLASH_Program(FLASH_TYPEPROGRAM_BURST, address, (uint32_t)data)) {
+ return secfalse;
+ }
+
+ for (int i = 0; i < FLASH_BURST_WORDS; i++) {
+ if (data[i] != *((const uint32_t *)address + i)) {
+ return secfalse;
+ }
+ }
+ return sectrue;
+}
+
+secbool flash_write_block(uint16_t sector, uint32_t offset,
+ const flash_block_t block) {
+ return flash_write_quadword(sector, offset, block);
+}
+
+#endif // KERNEL_MODE
diff --git a/core/embed/sys/flash/stm32u5/flash_layout.c b/core/embed/sys/flash/stm32u5/flash_layout.c
new file mode 100644
index 00000000..bbdafa20
--- /dev/null
+++ b/core/embed/sys/flash/stm32u5/flash_layout.c
@@ -0,0 +1,79 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef KERNEL_MODE
+
+#include <trezor_bsp.h>
+#include <trezor_model.h>
+
+#include <sys/flash.h>
+
+#include "../layout_helpers.h"
+
+// Convert sector number to address
+//
+// This conversion is used in static assert in definitions below
+#define FLASH_SECTOR_TO_ADDR(sector, nonsecure) \
+ (((nonsecure) ? FLASH_BASE_NS : FLASH_BASE_S) + (sector) * FLASH_PAGE_SIZE)
+
+// Define all flash areas as `const flash_area_t ID = { .. };`
+
+#ifdef USE_SECMON_LAYOUT
+#define ACCESS_APP ACCESS_NONSECURE
+#else
+#define ACCESS_APP ACCESS_DEFAULT
+#endif
+
+#ifdef SECURE_MODE
+DEFINE_SINGLE_AREA(BOARDLOADER_AREA, BOARDLOADER, ACCESS_DEFAULT);
+DEFINE_SINGLE_AREA(BOOTLOADER_AREA, BOOTLOADER, ACCESS_DEFAULT);
+DEFINE_SINGLE_AREA(SECRET_AREA, SECRET, ACCESS_DEFAULT);
+DEFINE_SINGLE_AREA(BHK_AREA, BHK, ACCESS_DEFAULT);
+DEFINE_ARRAY2_AREA(STORAGE_AREAS, STORAGE_1, STORAGE_2, ACCESS_DEFAULT);
+DEFINE_EMPTY_AREA(UNUSED_AREA);
+
+#ifdef SECMON
+// FIRMWARE_AREA is defined in flash.c driver because it depends on the
+// SECMON size which is not known at compile time.
+#else
+DEFINE_SINGLE_AREA(FIRMWARE_AREA, FIRMWARE, ACCESS_DEFAULT);
+#endif
+
+#endif // SECURE_MODE
+
+#ifdef KERNEL_MODE
+DEFINE_SINGLE_AREA(ASSETS_AREA, ASSETS, ACCESS_APP);
+#endif
+
+#ifdef USE_BOOT_UCB
+// Area dedicated to the UCB (Update Control Block) used during
+// boot-loader or boot-header updates.
+DEFINE_SINGLE_AREA(BOOTUCB_AREA, BOOTUCB, ACCESS_DEFAULT);
+// Area used during bootloader update in prodtest. It holds
+// the downloaded bootloader image.
+DEFINE_SINGLE_AREA(BOOTUPDATE_AREA, BOOTUPDATE, ACCESS_DEFAULT);
+#ifdef BOARDLOADER
+// Area used by the boardloader during bootloader update process.
+// It includes the entire flash memory except the board-loader,
+// the UCB, and the secrets area.
+DEFINE_SINGLE_AREA(NONBOARDLOADER_AREA, NONBOARDLOADER, ACCESS_DEFAULT);
+#endif
+#endif
+
+#endif // KERNEL_MODE
diff --git a/core/embed/sys/flash/stm32u5/flash_otp.c b/core/embed/sys/flash/stm32u5/flash_otp.c
new file mode 100644
index 00000000..ccfe8510
--- /dev/null
+++ b/core/embed/sys/flash/stm32u5/flash_otp.c
@@ -0,0 +1,131 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef SECURE_MODE
+
+#include <trezor_bsp.h>
+#include <trezor_rtl.h>
+
+#include <sys/flash.h>
+#include <sys/flash_otp.h>
+#include <sys/mpu.h>
+
+void flash_otp_init() {
+ // intentionally left empty
+}
+
+secbool flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data,
+ uint8_t datalen) {
+ if (block >= FLASH_OTP_NUM_BLOCKS ||
+ offset + datalen > FLASH_OTP_BLOCK_SIZE) {
+ return secfalse;
+ }
+
+ mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP);
+
+ for (uint8_t i = 0; i < datalen; i++) {
+ data[i] = *(__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE +
+ offset + i);
+ }
+
+ mpu_restore(mpu_mode);
+
+ return sectrue;
+}
+
+secbool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data,
+ uint8_t datalen) {
+ if (datalen % 16 != 0) {
+ return secfalse;
+ }
+ if (block >= FLASH_OTP_NUM_BLOCKS ||
+ offset + datalen > FLASH_OTP_BLOCK_SIZE) {
+ return secfalse;
+ }
+
+ mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP);
+
+ ensure(flash_unlock_write(), NULL);
+ for (uint8_t i = 0; i < datalen; i += 16) {
+ uint32_t address =
+ FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE + offset + i;
+ ensure(sectrue * (HAL_OK == HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD_NS,
+ address, (uint32_t)&data[i])),
+ NULL);
+ }
+ ensure(flash_lock_write(), NULL);
+
+ mpu_restore(mpu_mode);
+
+ return sectrue;
+}
+
+secbool flash_otp_lock(uint8_t block) {
+ if (block >= FLASH_OTP_NUM_BLOCKS) {
+ return secfalse;
+ }
+
+ // check that all quadwords in the block have been written to
+ volatile uint8_t *addr =
+ (__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE);
+
+ mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP);
+
+ secbool qw_locked = secfalse;
+ for (uint8_t i = 0; i < FLASH_OTP_BLOCK_SIZE; i++) {
+ if (addr[i] != 0xFF) {
+ qw_locked = sectrue;
+ }
+ if (i % 16 == 15 && qw_locked == secfalse) {
+ mpu_restore(mpu_mode);
+ return secfalse;
+ }
+ }
+
+ mpu_restore(mpu_mode);
+
+ return sectrue;
+}
+
+secbool flash_otp_is_locked(uint8_t block) {
+ if (block >= FLASH_OTP_NUM_BLOCKS) {
+ return secfalse;
+ }
+
+ secbool is_locked = secfalse;
+
+ // considering block locked if any quadword in the block is non-0xFF
+ volatile uint8_t *addr =
+ (__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE);
+
+ mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP);
+
+ for (uint8_t i = 0; i < FLASH_OTP_BLOCK_SIZE; i++) {
+ if (addr[i] != 0xFF) {
+ is_locked = sectrue;
+ break;
+ }
+ }
+
+ mpu_restore(mpu_mode);
+
+ return is_locked;
+}
+
+#endif // SECURE_MODE
diff --git a/core/embed/sys/flash/unix/flash.c b/core/embed/sys/flash/unix/flash.c
new file mode 100644
index 00000000..79eeb44c
--- /dev/null
+++ b/core/embed/sys/flash/unix/flash.c
@@ -0,0 +1,229 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <trezor_model.h>
+#include <trezor_rtl.h>
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <sys/flash.h>
+#include "profile.h"
+
+#ifndef FLASH_FILE
+#define FLASH_FILE profile_flash_path()
+#endif
+
+#if defined STM32F427xx || defined STM32F429xx
+#define FLASH_SECTOR_COUNT 24
+#elif defined STM32U585xx
+#define FLASH_SECTOR_COUNT 256
+#elif defined STM32U5G9xx
+#define FLASH_SECTOR_COUNT 512
+#else
+#error Unknown MCU
+#endif
+
+static uint32_t FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT + 1] = {
+#if defined STM32F427xx || defined STM32F429xx
+ [0] = 0x08000000, // - 0x08003FFF | 16 KiB
+ [1] = 0x08004000, // - 0x08007FFF | 16 KiB
+ [2] = 0x08008000, // - 0x0800BFFF | 16 KiB
+ [3] = 0x0800C000, // - 0x0800FFFF | 16 KiB
+ [4] = 0x08010000, // - 0x0801FFFF | 64 KiB
+ [5] = 0x08020000, // - 0x0803FFFF | 128 KiB
+ [6] = 0x08040000, // - 0x0805FFFF | 128 KiB
+ [7] = 0x08060000, // - 0x0807FFFF | 128 KiB
+ [8] = 0x08080000, // - 0x0809FFFF | 128 KiB
+ [9] = 0x080A0000, // - 0x080BFFFF | 128 KiB
+ [10] = 0x080C0000, // - 0x080DFFFF | 128 KiB
+ [11] = 0x080E0000, // - 0x080FFFFF | 128 KiB
+ [12] = 0x08100000, // - 0x08103FFF | 16 KiB
+ [13] = 0x08104000, // - 0x08107FFF | 16 KiB
+ [14] = 0x08108000, // - 0x0810BFFF | 16 KiB
+ [15] = 0x0810C000, // - 0x0810FFFF | 16 KiB
+ [16] = 0x08110000, // - 0x0811FFFF | 64 KiB
+ [17] = 0x08120000, // - 0x0813FFFF | 128 KiB
+ [18] = 0x08140000, // - 0x0815FFFF | 128 KiB
+ [19] = 0x08160000, // - 0x0817FFFF | 128 KiB
+ [20] = 0x08180000, // - 0x0819FFFF | 128 KiB
+ [21] = 0x081A0000, // - 0x081BFFFF | 128 KiB
+ [22] = 0x081C0000, // - 0x081DFFFF | 128 KiB
+ [23] = 0x081E0000, // - 0x081FFFFF | 128 KiB
+ [24] = 0x08200000, // last element - not a valid sector
+#elif defined STM32U585xx || defined STM32U5G9xx
+ [0] = 0x08000000, // - 0x08001FFF | 8 KiB
+ // rest is initialized in flash_init
+#else
+#error Unknown MCU
+#endif
+};
+
+static uint8_t *FLASH_BUFFER = NULL;
+static uint32_t FLASH_SIZE;
+
+static void flash_exit(void) {
+ int r = munmap(FLASH_BUFFER, FLASH_SIZE);
+ ensure(sectrue * (r == 0), "munmap failed");
+}
+
+void flash_init(void) {
+ if (FLASH_BUFFER) return;
+
+#if defined STM32U585xx || defined STM32U5G9xx
+ for (size_t i = 0; i < FLASH_SECTOR_COUNT; i++) {
+ FLASH_SECTOR_TABLE[i + 1] =
+ FLASH_SECTOR_TABLE[i] + 0x2000; // 8KiB size sectors
+ }
+#endif
+
+ FLASH_SIZE = FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT] - FLASH_SECTOR_TABLE[0];
+
+ // check whether the file exists and it has the correct size
+ struct stat sb;
+ int r = stat(FLASH_FILE, &sb);
+
+ // (re)create if non existent or wrong size
+ if (r != 0 || sb.st_size != FLASH_SIZE) {
+ int fd = open(FLASH_FILE, O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
+ ensure(sectrue * (fd >= 0), "open failed");
+ for (int i = 0; i < FLASH_SIZE / 16; i++) {
+ ssize_t s = write(
+ fd,
+ "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
+ 16);
+ ensure(sectrue * (s >= 0), "write failed");
+ }
+ r = close(fd);
+ ensure(sectrue * (r == 0), "close failed");
+ }
+
+ // mmap file
+ int fd = open(FLASH_FILE, O_RDWR);
+ ensure(sectrue * (fd >= 0), "open failed");
+
+ void *map = mmap(0, FLASH_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ ensure(sectrue * (map != MAP_FAILED), "mmap failed");
+
+ FLASH_BUFFER = (uint8_t *)map;
+
+ atexit(flash_exit);
+}
+
+secbool flash_unlock_write(void) { return sectrue; }
+
+secbool flash_lock_write(void) { return sectrue; }
+
+const void *flash_get_address(uint16_t sector, uint32_t offset, uint32_t size) {
+ if (sector >= FLASH_SECTOR_COUNT) {
+ return NULL;
+ }
+ const uint32_t addr = FLASH_SECTOR_TABLE[sector] + offset;
+ const uint32_t next = FLASH_SECTOR_TABLE[sector + 1];
+ if (addr + size > next) {
+ return NULL;
+ }
+ return FLASH_BUFFER + addr - FLASH_SECTOR_TABLE[0];
+}
+
+uint32_t flash_sector_size(uint16_t first_sector, uint16_t sector_count) {
+ if (first_sector + sector_count > FLASH_SECTOR_COUNT) {
+ return 0;
+ }
+ return FLASH_SECTOR_TABLE[first_sector + sector_count] -
+ FLASH_SECTOR_TABLE[first_sector];
+}
+
+uint16_t flash_sector_find(uint16_t first_sector, uint32_t offset) {
+ uint16_t sector = first_sector;
+
+ while (sector < FLASH_SECTOR_COUNT) {
+ uint32_t sector_size =
+ FLASH_SECTOR_TABLE[sector + 1] - FLASH_SECTOR_TABLE[sector];
+
+ if (offset < sector_size) {
+ break;
+ }
+ offset -= sector_size;
+ sector++;
+ }
+
+ return sector;
+}
+
+secbool flash_sector_erase(uint16_t sector) {
+ if (sector >= FLASH_SECTOR_COUNT) {
+ return secfalse;
+ }
+
+ 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);
+
+ return sectrue;
+}
+
+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;
+ }
+ if ((flash[0] & data) != data) {
+ return secfalse; // we cannot change zeroes to ones
+ }
+ flash[0] = data;
+ return sectrue;
+}
+
+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;
+ }
+ uint32_t *flash = (uint32_t *)flash_get_address(sector, offset, sizeof(data));
+ if (!flash) {
+ return secfalse;
+ }
+ if ((flash[0] & data) != data) {
+ return secfalse; // we cannot change zeroes to ones
+ }
+ flash[0] = data;
+ return sectrue;
+}
+
+secbool flash_write_block(uint16_t sector, uint32_t offset,
+ const flash_block_t block) {
+ if (offset % (sizeof(uint32_t) *
+ FLASH_BLOCK_WORDS)) { // we write only at block boundary
+ return secfalse;
+ }
+
+ for (int i = 0; i < FLASH_BLOCK_WORDS; i++) {
+ if (!flash_write_word(sector, offset + i * sizeof(uint32_t), block[i])) {
+ return secfalse;
+ }
+ }
+ return sectrue;
+}
diff --git a/core/embed/sys/flash/unix/flash_otp.c b/core/embed/sys/flash/unix/flash_otp.c
new file mode 100644
index 00000000..447d0caf
--- /dev/null
+++ b/core/embed/sys/flash/unix/flash_otp.c
@@ -0,0 +1,62 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <trezor_rtl.h>
+
+#include <sys/flash_otp.h>
+
+#define OTP_BLOCK_SIZE 32
+#define FLASH_SECTOR_OTP (FLASH_SECTOR_COUNT)
+
+static uint8_t OTP_BUFFER[OTP_BLOCK_SIZE * 64];
+
+void flash_otp_init(void) {
+ // fill OTP buffer with ones
+ memset(OTP_BUFFER, 0xFF, sizeof(OTP_BUFFER));
+}
+
+secbool flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data,
+ uint8_t datalen) {
+ if (offset + datalen > OTP_BLOCK_SIZE) {
+ return secfalse;
+ }
+ uint32_t offset_in_sector = block * OTP_BLOCK_SIZE + offset;
+ memcpy(data, OTP_BUFFER + offset_in_sector, datalen);
+ return sectrue;
+}
+
+secbool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data,
+ uint8_t datalen) {
+ if (offset + datalen > OTP_BLOCK_SIZE) {
+ return secfalse;
+ }
+ uint32_t offset_in_sector = block * OTP_BLOCK_SIZE + offset;
+ uint8_t *flash = OTP_BUFFER + offset_in_sector;
+ for (int i = 0; i < datalen; i++) {
+ if ((flash[i] & data[i]) != data[i]) {
+ return secfalse; // we cannot change zeroes to ones
+ }
+ flash[i] = data[i];
+ }
+ return sectrue;
+}
+
+secbool flash_otp_lock(uint8_t block) { return secfalse; }
+
+secbool flash_otp_is_locked(uint8_t block) { return secfalse; }
diff --git a/core/embed/util/flash/flash_utils.c b/core/embed/util/flash/flash_utils.c
deleted file mode 100644
index 67952f95..00000000
--- a/core/embed/util/flash/flash_utils.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <trezor_model.h>
-#include <trezor_rtl.h>
-
-#include <sys/mpu.h>
-#include <util/flash.h>
-#include <util/flash_utils.h>
-
-typedef struct {
- const flash_area_t* area;
- mpu_mode_t mpu_mode;
-} flash_area_ref_t;
-
-// Erases the given list of flash areas.
-//
-// Invokes the progress_cb after each erased sector or page.
-static secbool erase_areas(const flash_area_ref_t* areas, int area_count,
- flash_progress_callback_t progress_cb) {
- int total = 0;
- int progress = 0;
-
- for (int i = 0; i < area_count; i++) {
- total += flash_area_get_size(areas[i].area);
- }
-
- mpu_mode_t mpu_mode = mpu_get_mode();
-
- for (int i = 0; i < area_count; i++) {
- const flash_area_t* area = areas[i].area;
- uint32_t offset = 0;
- uint32_t bytes_erased = 0;
-
- mpu_reconfig(areas[i].mpu_mode);
-
- do {
- if (progress_cb) {
- progress_cb(progress, total);
- }
-
- if (sectrue != flash_area_erase_partial(area, offset, &bytes_erased)) {
- mpu_restore(mpu_mode);
- return secfalse;
- }
-
- offset += bytes_erased;
- progress += bytes_erased;
-
- } while (bytes_erased > 0);
- }
-
- mpu_restore(mpu_mode);
- return sectrue;
-}
-
-secbool erase_storage(flash_progress_callback_t progress_cb) {
- _Static_assert(STORAGE_AREAS_COUNT == 2,
- "Unsupported number of storage areas");
-
- static const flash_area_ref_t areas[] = {
- {.area = &STORAGE_AREAS[0], .mpu_mode = MPU_MODE_STORAGE},
- {.area = &STORAGE_AREAS[1], .mpu_mode = MPU_MODE_STORAGE},
- };
-
- return erase_areas(areas, ARRAY_LENGTH(areas), progress_cb);
-}
-
-secbool erase_device(flash_progress_callback_t progress_cb) {
- _Static_assert(STORAGE_AREAS_COUNT == 2,
- "Unsupported number of storage areas");
-
- static const flash_area_ref_t areas[] = {
- {.area = &STORAGE_AREAS[0], .mpu_mode = MPU_MODE_STORAGE},
- {.area = &STORAGE_AREAS[1], .mpu_mode = MPU_MODE_STORAGE},
- {.area = &ASSETS_AREA, .mpu_mode = MPU_MODE_ASSETS},
-#if defined(BOARDLOADER) || defined(BOOTLOADER)
- {.area = &FIRMWARE_AREA, .mpu_mode = MPU_MODE_DEFAULT},
-#endif
-#if defined(BOARDLOADER) && defined(USE_SD_CARD)
- {.area = &BOOTLOADER_AREA, .mpu_mode = MPU_MODE_DEFAULT},
- {.area = &UNUSED_AREA, .mpu_mode = MPU_MODE_UNUSED_FLASH},
-#endif
- };
-
- return erase_areas(areas, ARRAY_LENGTH(areas), progress_cb);
-}
diff --git a/core/embed/util/flash/inc/norcow_config.h b/core/embed/util/flash/inc/norcow_config.h
deleted file mode 100644
index 36dc6ad3..00000000
--- a/core/embed/util/flash/inc/norcow_config.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __NORCOW_CONFIG_H__
-#define __NORCOW_CONFIG_H__
-
-#include <trezor_model.h>
-#include <trezor_types.h>
-
-#include <util/flash.h>
-
-#define NORCOW_HEADER_LEN 0
-#define NORCOW_SECTOR_COUNT 2
-
-#define STORAGE_AREAS_COUNT NORCOW_SECTOR_COUNT
-extern const flash_area_t STORAGE_AREAS[STORAGE_AREAS_COUNT];
-
-/*
- * Current storage version.
- */
-#define NORCOW_VERSION ((uint32_t)0x00000006)
-
-#endif
diff --git a/core/embed/util/flash/inc/util/flash.h b/core/embed/util/flash/inc/util/flash.h
deleted file mode 100644
index 43d22f18..00000000
--- a/core/embed/util/flash/inc/util/flash.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#ifdef KERNEL_MODE
-
-#include <trezor_types.h>
-
-#include <trezor-storage/flash_area.h>
-#include <trezor-storage/flash_ll.h>
-
-#include "../norcow_config.h"
-
-void flash_init(void);
-
-extern const flash_area_t BOARDLOADER_AREA;
-extern const flash_area_t SECRET_AREA;
-extern const flash_area_t BHK_AREA;
-extern const flash_area_t ASSETS_AREA;
-extern const flash_area_t BOOTLOADER_AREA;
-extern const flash_area_t UNUSED_AREA;
-
-#ifdef SECMON
-extern flash_area_t FIRMWARE_AREA;
-#else
-extern const flash_area_t FIRMWARE_AREA;
-#endif
-
-#ifdef USE_BOOT_UCB
-extern const flash_area_t BOOTUCB_AREA;
-extern const flash_area_t BOOTUPDATE_AREA;
-#ifdef BOARDLOADER
-extern const flash_area_t NONBOARDLOADER_AREA;
-#endif
-#endif // USE_BOOT_UCB
-
-#endif // KERNEL_MODE
diff --git a/core/embed/util/flash/inc/util/flash_otp.h b/core/embed/util/flash/inc/util/flash_otp.h
deleted file mode 100644
index 4996916c..00000000
--- a/core/embed/util/flash/inc/util/flash_otp.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include <trezor_types.h>
-
-#ifdef SECURE_MODE
-
-#define FLASH_OTP_NUM_BLOCKS 16
-#define FLASH_OTP_BLOCK_SIZE 32
-
-void flash_otp_init(void);
-
-secbool __wur flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data,
- uint8_t datalen);
-secbool __wur flash_otp_write(uint8_t block, uint8_t offset,
- const uint8_t *data, uint8_t datalen);
-secbool __wur flash_otp_lock(uint8_t block);
-secbool __wur flash_otp_is_locked(uint8_t block);
-
-#endif // SECURE_MODE
diff --git a/core/embed/util/flash/inc/util/flash_utils.h b/core/embed/util/flash/inc/util/flash_utils.h
deleted file mode 100644
index bd973fb9..00000000
--- a/core/embed/util/flash/inc/util/flash_utils.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef LIB_FLASH_UTILS_H
-#define LIB_FLASH_UTILS_H
-
-#include <trezor_types.h>
-
-#ifdef KERNEL_MODE
-
-// Progress callback function called during the flash erase operation.
-//
-// Progress is reported as: (100 * pos) / total [%].
-typedef void (*flash_progress_callback_t)(int pos, int total);
-
-// Erases both storage areas
-//
-// Callback is invoked after each sector or page is erased.
-secbool erase_storage(flash_progress_callback_t progress_cb);
-
-// Erases all flash areas including storage, assets and firmware.
-//
-// If called from boardloader, also erases bootloader area.
-//
-// Callback is invoked after each sector or page is erased.
-secbool erase_device(flash_progress_callback_t progress_cb);
-
-#endif // KERNEL_MODE
-
-#endif // LIB_FLASH_UTILS_H
diff --git a/core/embed/util/flash/layout_helpers.h b/core/embed/util/flash/layout_helpers.h
deleted file mode 100644
index 7d27ffcf..00000000
--- a/core/embed/util/flash/layout_helpers.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#ifdef TREZOR_EMULATOR
-#define ENSURE_SECTOR_AT(addr, sector, access)
-#else
-// Static assertions ensuring that the flash address coresponds
-// to the expected sector start. This macro is used in the
-// definitions below.
-#define ENSURE_SECTOR_AT(addr, sector, access) \
- _Static_assert(FLASH_SECTOR_TO_ADDR(EVAL(sector), access) == EVAL(addr), \
- "Sector address mismatch")
-#endif
-
-#define ACCESS_DEFAULT 0
-#define ACCESS_NONSECURE 1
-
-// Helper that expands to its argument
-#define EVAL(x) x
-
-// Defines flash_subarea_t structure
-#define SUBAREA(_first_sector, _end_sectors) \
- { \
- .first_sector = (_first_sector), \
- .num_sectors = (_end_sectors) - (_first_sector) + 1, \
- }
-
-// Defines flash area containing 1 subarea
-#define DEFINE_SINGLE_AREA(id, prefix, access) \
- ENSURE_SECTOR_AT(prefix##_START, prefix##_SECTOR_START, access); \
- ENSURE_SECTOR_AT(prefix##_START + prefix##_MAXSIZE, prefix##_SECTOR_END + 1, \
- access); \
- const flash_area_t prefix##_AREA = { \
- .num_subareas = 1, \
- .subarea[0] = SUBAREA(prefix##_SECTOR_START, prefix##_SECTOR_END), \
- }
-
-// Defines flash area containing two subareas from two
-// different blocks giveng by their prefixes
-#define DEFINE_SPLIT2_AREA(id, prefix1, access1, prefix2, access2) \
- ENSURE_SECTOR_AT(prefix1##_START, prefix1##_SECTOR_START, access1); \
- ENSURE_SECTOR_AT(prefix1##_START + prefix1##_MAXSIZE, \
- prefix1##_SECTOR_END + 1, access1); \
- ENSURE_SECTOR_AT(prefix2##_START, prefix2##_SECTOR_START, access2); \
- ENSURE_SECTOR_AT(prefix2##_START + prefix2##_MAXSIZE, \
- prefix2##_SECTOR_END + 1, access2); \
- const flash_area_t id = { \
- .num_subareas = 2, \
- .subarea[0] = SUBAREA(prefix1##_SECTOR_START, prefix1##_SECTOR_END), \
- .subarea[1] = SUBAREA(prefix2##_SECTOR_START, prefix2##_SECTOR_END), \
- }
-
-// Defines array of two flash areas from two differenc blocks
-// given by their prefixes
-#define DEFINE_ARRAY2_AREA(id, prefix1, prefix2, access) \
- ENSURE_SECTOR_AT(prefix1##_START, prefix1##_SECTOR_START, access); \
- ENSURE_SECTOR_AT(prefix1##_START + prefix1##_MAXSIZE, \
- prefix1##_SECTOR_END + 1, access); \
- ENSURE_SECTOR_AT(prefix2##_START, prefix2##_SECTOR_START, access); \
- ENSURE_SECTOR_AT(prefix2##_START + prefix2##_MAXSIZE, \
- prefix2##_SECTOR_END + 1, access); \
- const flash_area_t id[] = { \
- { \
- .num_subareas = 1, \
- .subarea[0] = SUBAREA(prefix1##_SECTOR_START, prefix1##_SECTOR_END), \
- }, \
- { \
- .num_subareas = 1, \
- .subarea[0] = SUBAREA(prefix2##_SECTOR_START, prefix2##_SECTOR_END), \
- }}
-
-#define DEFINE_EMPTY_AREA(id) const flash_area_t id = {.num_subareas = 0}
diff --git a/core/embed/util/flash/stm32f4/flash.c b/core/embed/util/flash/stm32f4/flash.c
deleted file mode 100644
index f9598cec..00000000
--- a/core/embed/util/flash/stm32f4/flash.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <trezor_bsp.h>
-#include <trezor_rtl.h>
-
-#include <util/flash.h>
-
-#ifdef KERNEL_MODE
-
-#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] = {
- [0] = 0x08000000, // - 0x08003FFF | 16 KiB
- [1] = 0x08004000, // - 0x08007FFF | 16 KiB
- [2] = 0x08008000, // - 0x0800BFFF | 16 KiB
- [3] = 0x0800C000, // - 0x0800FFFF | 16 KiB
- [4] = 0x08010000, // - 0x0801FFFF | 64 KiB
- [5] = 0x08020000, // - 0x0803FFFF | 128 KiB
- [6] = 0x08040000, // - 0x0805FFFF | 128 KiB
- [7] = 0x08060000, // - 0x0807FFFF | 128 KiB
- [8] = 0x08080000, // - 0x0809FFFF | 128 KiB
- [9] = 0x080A0000, // - 0x080BFFFF | 128 KiB
- [10] = 0x080C0000, // - 0x080DFFFF | 128 KiB
- [11] = 0x080E0000, // - 0x080FFFFF | 128 KiB
-#if defined STM32F427xx || defined STM32F429xx
- [12] = 0x08100000, // - 0x08103FFF | 16 KiB
- [13] = 0x08104000, // - 0x08107FFF | 16 KiB
- [14] = 0x08108000, // - 0x0810BFFF | 16 KiB
- [15] = 0x0810C000, // - 0x0810FFFF | 16 KiB
- [16] = 0x08110000, // - 0x0811FFFF | 64 KiB
- [17] = 0x08120000, // - 0x0813FFFF | 128 KiB
- [18] = 0x08140000, // - 0x0815FFFF | 128 KiB
- [19] = 0x08160000, // - 0x0817FFFF | 128 KiB
- [20] = 0x08180000, // - 0x0819FFFF | 128 KiB
- [21] = 0x081A0000, // - 0x081BFFFF | 128 KiB
- [22] = 0x081C0000, // - 0x081DFFFF | 128 KiB
- [23] = 0x081E0000, // - 0x081FFFFF | 128 KiB
- [24] = 0x08200000, // last element - not a valid sector
-#elif defined STM32F405xx
- [12] = 0x08100000, // last element - not a valid sector
-#else
-#error Unknown MCU
-#endif
-};
-
-const void *flash_get_address(uint16_t sector, uint32_t offset, uint32_t size) {
- if (sector >= FLASH_SECTOR_COUNT) {
- return NULL;
- }
- const uint32_t addr = FLASH_SECTOR_TABLE[sector] + offset;
- const uint32_t next = FLASH_SECTOR_TABLE[sector + 1];
- if (addr + size > next) {
- return NULL;
- }
- return (const void *)addr;
-}
-
-uint32_t flash_sector_size(uint16_t first_sector, uint16_t sector_count) {
- if (first_sector + sector_count > FLASH_SECTOR_COUNT) {
- return 0;
- }
- return FLASH_SECTOR_TABLE[first_sector + sector_count] -
- FLASH_SECTOR_TABLE[first_sector];
-}
-
-uint16_t flash_sector_find(uint16_t first_sector, uint32_t offset) {
- uint16_t sector = first_sector;
-
- while (sector < FLASH_SECTOR_COUNT) {
- uint32_t sector_size =
- FLASH_SECTOR_TABLE[sector + 1] - FLASH_SECTOR_TABLE[sector];
-
- if (offset < sector_size) {
- break;
- }
- offset -= sector_size;
- sector++;
- }
-
- return sector;
-}
-
-secbool flash_unlock_write(void) {
- HAL_FLASH_Unlock();
- FLASH->SR |= FLASH_STATUS_ALL_FLAGS; // clear all status flags
- return sectrue;
-}
-
-secbool flash_lock_write(void) {
- HAL_FLASH_Lock();
- return sectrue;
-}
-
-secbool flash_sector_erase(uint16_t sector) {
- if (sector >= FLASH_SECTOR_COUNT) {
- return secfalse;
- }
-
- FLASH_EraseInitTypeDef EraseInitStruct = {
- .TypeErase = FLASH_TYPEERASE_SECTORS,
- .VoltageRange = FLASH_VOLTAGE_RANGE_3,
- .Sector = sector,
- .NbSectors = 1,
- };
-
- uint32_t sector_error;
-
- if (HAL_FLASHEx_Erase(&EraseInitStruct, §or_error) != HAL_OK) {
- return secfalse;
- }
-
- // check whether the sector was really deleted (contains only 0xFF)
- uint32_t addr_start = FLASH_SECTOR_TABLE[sector];
- uint32_t addr_end = FLASH_SECTOR_TABLE[sector + 1];
-
- for (uint32_t addr = addr_start; addr < addr_end; addr += 4) {
- if (*((const uint32_t *)addr) != 0xFFFFFFFF) {
- return secfalse;
- }
- }
-
- return sectrue;
-}
-
-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;
- }
- if (data != (data & *((const uint8_t *)address))) {
- return secfalse;
- }
- if (HAL_OK != HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, address, data)) {
- return secfalse;
- }
- if (data != *((const uint8_t *)address)) {
- return secfalse;
- }
- return sectrue;
-}
-
-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;
- }
- if (offset % sizeof(uint32_t)) { // we write only at 4-byte boundary
- return secfalse;
- }
- if (data != (data & *((const uint32_t *)address))) {
- return secfalse;
- }
- if (HAL_OK != HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, data)) {
- return secfalse;
- }
- if (data != *((const uint32_t *)address)) {
- 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]);
-}
-
-#endif // KERNEL_MODE
diff --git a/core/embed/util/flash/stm32f4/flash_layout.c b/core/embed/util/flash/stm32f4/flash_layout.c
deleted file mode 100644
index ee2d84aa..00000000
--- a/core/embed/util/flash/stm32f4/flash_layout.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef KERNEL_MODE
-
-#include <trezor_bsp.h>
-#include <trezor_model.h>
-
-#include <util/flash.h>
-
-#include "../layout_helpers.h"
-
-// Convert sector number to address
-//
-// This conversion is used in static assert in definitions below
-#define FLASH_SECTOR_TO_ADDR(sector, nonsecure) \
- (FLASH_BASE + ((sector) / 12) * 0x100000 + \
- (((sector) % 12) < 4 \
- ? ((sector) % 12) * 0x4000 \
- : (((sector) % 12) < 5 ? 0x10000 : ((sector) % 12 - 4) * 0x20000)))
-
-// Define all flash areas as `const flash_area_t ID = { .. };`
-
-DEFINE_ARRAY2_AREA(STORAGE_AREAS, STORAGE_1, STORAGE_2, ACCESS_DEFAULT);
-DEFINE_SINGLE_AREA(BOARDLOADER_AREA, BOARDLOADER, ACCESS_DEFAULT);
-DEFINE_SINGLE_AREA(BOOTLOADER_AREA, BOOTLOADER, ACCESS_DEFAULT);
-DEFINE_SPLIT2_AREA(FIRMWARE_AREA, FIRMWARE_P1, ACCESS_DEFAULT, FIRMWARE_P2,
- ACCESS_DEFAULT);
-
-#ifdef SECRET_SECTOR_START
-DEFINE_SINGLE_AREA(SECRET_AREA, SECRET, ACCESS_DEFAULT);
-#else
-DEFINE_EMPTY_AREA(SECRET_AREA);
-#endif
-
-DEFINE_SINGLE_AREA(ASSETS_AREA, ASSETS, ACCESS_DEFAULT);
-DEFINE_SPLIT2_AREA(UNUSED_AREA, UNUSED_1, ACCESS_DEFAULT, UNUSED_2,
- ACCESS_DEFAULT);
-
-#endif // KERNEL_MODE
diff --git a/core/embed/util/flash/stm32f4/flash_otp.c b/core/embed/util/flash/stm32f4/flash_otp.c
deleted file mode 100644
index 60990b44..00000000
--- a/core/embed/util/flash/stm32f4/flash_otp.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <trezor_bsp.h>
-#include <trezor_rtl.h>
-
-#include <sys/mpu.h>
-#include <util/flash.h>
-#include <util/flash_otp.h>
-
-#ifdef KERNEL_MODE
-
-#define FLASH_OTP_LOCK_BASE 0x1FFF7A00U
-
-void flash_otp_init() {
- // intentionally left empty
-}
-
-secbool flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data,
- uint8_t datalen) {
- if (block >= FLASH_OTP_NUM_BLOCKS ||
- offset + datalen > FLASH_OTP_BLOCK_SIZE) {
- return secfalse;
- }
-
- mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP);
-
- for (uint8_t i = 0; i < datalen; i++) {
- data[i] = *(__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE +
- offset + i);
- }
-
- mpu_restore(mpu_mode);
-
- return sectrue;
-}
-
-secbool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data,
- uint8_t datalen) {
- if (block >= FLASH_OTP_NUM_BLOCKS ||
- offset + datalen > FLASH_OTP_BLOCK_SIZE) {
- return secfalse;
- }
-
- mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP);
-
- ensure(flash_unlock_write(), NULL);
- for (uint8_t i = 0; i < datalen; i++) {
- uint32_t address =
- FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE + offset + i;
- ensure(sectrue * (HAL_OK == HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE,
- address, data[i])),
- NULL);
- }
- ensure(flash_lock_write(), NULL);
-
- mpu_restore(mpu_mode);
-
- return sectrue;
-}
-
-secbool flash_otp_lock(uint8_t block) {
- if (block >= FLASH_OTP_NUM_BLOCKS) {
- return secfalse;
- }
-
- mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP);
-
- ensure(flash_unlock_write(), NULL);
- HAL_StatusTypeDef ret = HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE,
- FLASH_OTP_LOCK_BASE + block, 0x00);
- ensure(flash_lock_write(), NULL);
-
- mpu_restore(mpu_mode);
-
- return sectrue * (ret == HAL_OK);
-}
-
-secbool flash_otp_is_locked(uint8_t block) {
- secbool is_locked;
-
- mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP);
-
- is_locked =
- sectrue * (0x00 == *(__IO uint8_t *)(FLASH_OTP_LOCK_BASE + block));
-
- mpu_restore(mpu_mode);
-
- return is_locked;
-}
-
-#endif // KERNEL_MODE
diff --git a/core/embed/util/flash/stm32u5/flash.c b/core/embed/util/flash/stm32u5/flash.c
deleted file mode 100644
index 1f1536fc..00000000
--- a/core/embed/util/flash/stm32u5/flash.c
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <trezor_bsp.h>
-#include <trezor_model.h>
-#include <trezor_rtl.h>
-
-#include <util/flash.h>
-
-#ifdef KERNEL_MODE
-
-#ifdef STM32U585xx
-#define FLASH_BANK_PAGES 128
-#define FLASH_SECTOR_COUNT (FLASH_BANK_PAGES * 2)
-#else
-#define FLASH_BANK_PAGES 256
-#define FLASH_SECTOR_COUNT (FLASH_BANK_PAGES * 2)
-#endif
-
-#define FLASH_STATUS_ALL_FLAGS \
- (FLASH_NSSR_PGSERR | FLASH_NSSR_PGAERR | FLASH_NSSR_WRPERR | FLASH_NSSR_EOP)
-
-#ifdef SECMON
-extern uint32_t _codelen;
-#define SECMON_SIZE ((uint32_t) & _codelen)
-#define KERNEL_SECTOR_START \
- ((FIRMWARE_START_S + SECMON_SIZE - FLASH_BASE) / FLASH_PAGE_SIZE)
-
-flash_area_t FIRMWARE_AREA = {0};
-#endif // SECMON
-
-void flash_init(void) {
-#ifdef SECMON
- // FIRMWARE_AREA is defined here because it depends on the
- // SECMON size which is not known at compile time.
-
- FIRMWARE_AREA = (flash_area_t){
- .num_subareas = 2,
- .subarea[0] =
- {
- .first_sector = FIRMWARE_SECTOR_START,
- .num_sectors = KERNEL_SECTOR_START - FIRMWARE_SECTOR_START,
- },
- .subarea[1] =
- {
- .first_sector = KERNEL_SECTOR_START,
- .num_sectors = FIRMWARE_SECTOR_END - KERNEL_SECTOR_START + 1,
- },
- };
-#endif
-}
-
-static bool flash_sector_is_secure(uint32_t sector) {
-#if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
-#ifdef SECMON
- if (sector < KERNEL_SECTOR_START) {
- return true;
- } else if (sector >= STORAGE_1_SECTOR_START &&
- sector <= STORAGE_1_SECTOR_END) {
- return true;
- } else if (sector >= STORAGE_2_SECTOR_START &&
- sector <= STORAGE_2_SECTOR_END) {
- return true;
- }
-#else
- return true;
-#endif
-#endif
- return false;
-}
-
-const void *flash_get_address(uint16_t sector, uint32_t offset, uint32_t size) {
- if (sector >= FLASH_SECTOR_COUNT) {
- return NULL;
- }
-
- if (offset + size > FLASH_PAGE_SIZE) {
- return NULL;
- }
-
- uint32_t base_addr =
- flash_sector_is_secure(sector) ? FLASH_BASE_S : FLASH_BASE_NS;
-
- return (const void *)(base_addr + FLASH_PAGE_SIZE * sector + offset);
-}
-
-uint32_t flash_sector_size(uint16_t first_sector, uint16_t sector_count) {
- if (first_sector + sector_count > FLASH_SECTOR_COUNT) {
- return 0;
- }
- return FLASH_PAGE_SIZE * sector_count;
-}
-
-uint16_t flash_sector_find(uint16_t first_sector, uint32_t offset) {
- return first_sector + offset / FLASH_PAGE_SIZE;
-}
-
-secbool flash_unlock_write(void) {
- HAL_FLASH_Unlock();
- FLASH->NSSR |= FLASH_STATUS_ALL_FLAGS; // clear all status flags
-#if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
- FLASH->SECSR |= FLASH_STATUS_ALL_FLAGS; // clear all status flags
-#endif
- return sectrue;
-}
-
-secbool flash_lock_write(void) {
- HAL_FLASH_Lock();
- return sectrue;
-}
-
-secbool flash_sector_erase(uint16_t sector) {
- if (sector >= FLASH_SECTOR_COUNT) {
- return secfalse;
- }
-
- FLASH_EraseInitTypeDef EraseInitStruct = {
- .TypeErase = FLASH_TYPEERASE_PAGES,
- .Banks = FLASH_BANK_1,
- .Page = sector,
- .NbPages = 1,
- };
-
- if (sector >= FLASH_BANK_PAGES) {
- EraseInitStruct.Banks = FLASH_BANK_2;
- EraseInitStruct.Page = sector - FLASH_BANK_PAGES;
- }
-
- if (flash_sector_is_secure(sector)) {
- EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
- }
-
- uint32_t sector_error = 0;
-
- if (HAL_FLASHEx_Erase(&EraseInitStruct, §or_error) != HAL_OK) {
- return secfalse;
- }
-
- // check whether the sector was really deleted (contains only 0xFF)
- const uint32_t *sector_start =
- (const uint32_t *)flash_get_address(sector, 0, 0);
-
- const uint32_t *sector_end =
- sector_start + flash_sector_size(sector, 1) / sizeof(uint32_t);
-
- for (const uint32_t *addr = sector_start; addr < sector_end; addr++) {
- if (*addr != 0xFFFFFFFF) {
- return secfalse;
- }
- }
-
- return sectrue;
-}
-
-secbool flash_write_quadword(uint16_t sector, uint32_t offset,
- const uint32_t *data) {
- uint32_t address =
- (uint32_t)flash_get_address(sector, offset, FLASH_QUADWORD_SIZE);
- if (address == 0) {
- return secfalse;
- }
- if (offset % FLASH_QUADWORD_SIZE) { // we write only at 16-byte boundary
- return secfalse;
- }
-
- 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 < FLASH_QUADWORD_WORDS; i++) {
- if (data[i] != *((const uint32_t *)address + i)) {
- all_match = secfalse;
- break;
- }
- }
- if (all_match == sectrue) {
- return sectrue;
- }
-
- if (HAL_OK !=
- HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, address, (uint32_t)data)) {
- return secfalse;
- }
-
- for (int i = 0; i < FLASH_QUADWORD_WORDS; i++) {
- if (data[i] != *((const uint32_t *)address + i)) {
- return secfalse;
- }
- }
- return sectrue;
-}
-
-secbool flash_write_burst(uint16_t sector, uint32_t offset,
- const uint32_t *data) {
- uint32_t address =
- (uint32_t)flash_get_address(sector, offset, FLASH_BURST_SIZE);
- if (address == 0) {
- return secfalse;
- }
- if (offset % FLASH_BURST_SIZE) { // we write only at 128-byte boundary
- return secfalse;
- }
-
- for (int i = 0; i < FLASH_BURST_WORDS; i++) {
- if (data[i] != (data[i] & *((const uint32_t *)address + i))) {
- return secfalse;
- }
- }
-
- secbool all_match = sectrue;
- for (int i = 0; i < FLASH_BURST_WORDS; i++) {
- if (data[i] != *((const uint32_t *)address + i)) {
- all_match = secfalse;
- break;
- }
- }
- if (all_match == sectrue) {
- return sectrue;
- }
-
- if (HAL_OK !=
- HAL_FLASH_Program(FLASH_TYPEPROGRAM_BURST, address, (uint32_t)data)) {
- return secfalse;
- }
-
- for (int i = 0; i < FLASH_BURST_WORDS; i++) {
- if (data[i] != *((const uint32_t *)address + i)) {
- return secfalse;
- }
- }
- return sectrue;
-}
-
-secbool flash_write_block(uint16_t sector, uint32_t offset,
- const flash_block_t block) {
- return flash_write_quadword(sector, offset, block);
-}
-
-#endif // KERNEL_MODE
diff --git a/core/embed/util/flash/stm32u5/flash_layout.c b/core/embed/util/flash/stm32u5/flash_layout.c
deleted file mode 100644
index cb711a0d..00000000
--- a/core/embed/util/flash/stm32u5/flash_layout.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef KERNEL_MODE
-
-#include <trezor_bsp.h>
-#include <trezor_model.h>
-
-#include <util/flash.h>
-
-#include "../layout_helpers.h"
-
-// Convert sector number to address
-//
-// This conversion is used in static assert in definitions below
-#define FLASH_SECTOR_TO_ADDR(sector, nonsecure) \
- (((nonsecure) ? FLASH_BASE_NS : FLASH_BASE_S) + (sector) * FLASH_PAGE_SIZE)
-
-// Define all flash areas as `const flash_area_t ID = { .. };`
-
-#ifdef USE_SECMON_LAYOUT
-#define ACCESS_APP ACCESS_NONSECURE
-#else
-#define ACCESS_APP ACCESS_DEFAULT
-#endif
-
-#ifdef SECURE_MODE
-DEFINE_SINGLE_AREA(BOARDLOADER_AREA, BOARDLOADER, ACCESS_DEFAULT);
-DEFINE_SINGLE_AREA(BOOTLOADER_AREA, BOOTLOADER, ACCESS_DEFAULT);
-DEFINE_SINGLE_AREA(SECRET_AREA, SECRET, ACCESS_DEFAULT);
-DEFINE_SINGLE_AREA(BHK_AREA, BHK, ACCESS_DEFAULT);
-DEFINE_ARRAY2_AREA(STORAGE_AREAS, STORAGE_1, STORAGE_2, ACCESS_DEFAULT);
-DEFINE_EMPTY_AREA(UNUSED_AREA);
-
-#ifdef SECMON
-// FIRMWARE_AREA is defined in flash.c driver because it depends on the
-// SECMON size which is not known at compile time.
-#else
-DEFINE_SINGLE_AREA(FIRMWARE_AREA, FIRMWARE, ACCESS_DEFAULT);
-#endif
-
-#endif // SECURE_MODE
-
-#ifdef KERNEL_MODE
-DEFINE_SINGLE_AREA(ASSETS_AREA, ASSETS, ACCESS_APP);
-#endif
-
-#ifdef USE_BOOT_UCB
-// Area dedicated to the UCB (Update Control Block) used during
-// boot-loader or boot-header updates.
-DEFINE_SINGLE_AREA(BOOTUCB_AREA, BOOTUCB, ACCESS_DEFAULT);
-// Area used during bootloader update in prodtest. It holds
-// the downloaded bootloader image.
-DEFINE_SINGLE_AREA(BOOTUPDATE_AREA, BOOTUPDATE, ACCESS_DEFAULT);
-#ifdef BOARDLOADER
-// Area used by the boardloader during bootloader update process.
-// It includes the entire flash memory except the board-loader,
-// the UCB, and the secrets area.
-DEFINE_SINGLE_AREA(NONBOARDLOADER_AREA, NONBOARDLOADER, ACCESS_DEFAULT);
-#endif
-#endif
-
-#endif // KERNEL_MODE
diff --git a/core/embed/util/flash/stm32u5/flash_otp.c b/core/embed/util/flash/stm32u5/flash_otp.c
deleted file mode 100644
index 5a8f3d14..00000000
--- a/core/embed/util/flash/stm32u5/flash_otp.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef SECURE_MODE
-
-#include <trezor_bsp.h>
-#include <trezor_rtl.h>
-
-#include <sys/mpu.h>
-#include <util/flash.h>
-#include <util/flash_otp.h>
-
-void flash_otp_init() {
- // intentionally left empty
-}
-
-secbool flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data,
- uint8_t datalen) {
- if (block >= FLASH_OTP_NUM_BLOCKS ||
- offset + datalen > FLASH_OTP_BLOCK_SIZE) {
- return secfalse;
- }
-
- mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP);
-
- for (uint8_t i = 0; i < datalen; i++) {
- data[i] = *(__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE +
- offset + i);
- }
-
- mpu_restore(mpu_mode);
-
- return sectrue;
-}
-
-secbool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data,
- uint8_t datalen) {
- if (datalen % 16 != 0) {
- return secfalse;
- }
- if (block >= FLASH_OTP_NUM_BLOCKS ||
- offset + datalen > FLASH_OTP_BLOCK_SIZE) {
- return secfalse;
- }
-
- mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP);
-
- ensure(flash_unlock_write(), NULL);
- for (uint8_t i = 0; i < datalen; i += 16) {
- uint32_t address =
- FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE + offset + i;
- ensure(sectrue * (HAL_OK == HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD_NS,
- address, (uint32_t)&data[i])),
- NULL);
- }
- ensure(flash_lock_write(), NULL);
-
- mpu_restore(mpu_mode);
-
- return sectrue;
-}
-
-secbool flash_otp_lock(uint8_t block) {
- if (block >= FLASH_OTP_NUM_BLOCKS) {
- return secfalse;
- }
-
- // check that all quadwords in the block have been written to
- volatile uint8_t *addr =
- (__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE);
-
- mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP);
-
- secbool qw_locked = secfalse;
- for (uint8_t i = 0; i < FLASH_OTP_BLOCK_SIZE; i++) {
- if (addr[i] != 0xFF) {
- qw_locked = sectrue;
- }
- if (i % 16 == 15 && qw_locked == secfalse) {
- mpu_restore(mpu_mode);
- return secfalse;
- }
- }
-
- mpu_restore(mpu_mode);
-
- return sectrue;
-}
-
-secbool flash_otp_is_locked(uint8_t block) {
- if (block >= FLASH_OTP_NUM_BLOCKS) {
- return secfalse;
- }
-
- secbool is_locked = secfalse;
-
- // considering block locked if any quadword in the block is non-0xFF
- volatile uint8_t *addr =
- (__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE);
-
- mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP);
-
- for (uint8_t i = 0; i < FLASH_OTP_BLOCK_SIZE; i++) {
- if (addr[i] != 0xFF) {
- is_locked = sectrue;
- break;
- }
- }
-
- mpu_restore(mpu_mode);
-
- return is_locked;
-}
-
-#endif // SECURE_MODE
diff --git a/core/embed/util/flash/unix/flash.c b/core/embed/util/flash/unix/flash.c
deleted file mode 100644
index 6e402280..00000000
--- a/core/embed/util/flash/unix/flash.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <trezor_model.h>
-#include <trezor_rtl.h>
-
-#include <fcntl.h>
-#include <stdlib.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <util/flash.h>
-#include "profile.h"
-
-#ifndef FLASH_FILE
-#define FLASH_FILE profile_flash_path()
-#endif
-
-#if defined STM32F427xx || defined STM32F429xx
-#define FLASH_SECTOR_COUNT 24
-#elif defined STM32U585xx
-#define FLASH_SECTOR_COUNT 256
-#elif defined STM32U5G9xx
-#define FLASH_SECTOR_COUNT 512
-#else
-#error Unknown MCU
-#endif
-
-static uint32_t FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT + 1] = {
-#if defined STM32F427xx || defined STM32F429xx
- [0] = 0x08000000, // - 0x08003FFF | 16 KiB
- [1] = 0x08004000, // - 0x08007FFF | 16 KiB
- [2] = 0x08008000, // - 0x0800BFFF | 16 KiB
- [3] = 0x0800C000, // - 0x0800FFFF | 16 KiB
- [4] = 0x08010000, // - 0x0801FFFF | 64 KiB
- [5] = 0x08020000, // - 0x0803FFFF | 128 KiB
- [6] = 0x08040000, // - 0x0805FFFF | 128 KiB
- [7] = 0x08060000, // - 0x0807FFFF | 128 KiB
- [8] = 0x08080000, // - 0x0809FFFF | 128 KiB
- [9] = 0x080A0000, // - 0x080BFFFF | 128 KiB
- [10] = 0x080C0000, // - 0x080DFFFF | 128 KiB
- [11] = 0x080E0000, // - 0x080FFFFF | 128 KiB
- [12] = 0x08100000, // - 0x08103FFF | 16 KiB
- [13] = 0x08104000, // - 0x08107FFF | 16 KiB
- [14] = 0x08108000, // - 0x0810BFFF | 16 KiB
- [15] = 0x0810C000, // - 0x0810FFFF | 16 KiB
- [16] = 0x08110000, // - 0x0811FFFF | 64 KiB
- [17] = 0x08120000, // - 0x0813FFFF | 128 KiB
- [18] = 0x08140000, // - 0x0815FFFF | 128 KiB
- [19] = 0x08160000, // - 0x0817FFFF | 128 KiB
- [20] = 0x08180000, // - 0x0819FFFF | 128 KiB
- [21] = 0x081A0000, // - 0x081BFFFF | 128 KiB
- [22] = 0x081C0000, // - 0x081DFFFF | 128 KiB
- [23] = 0x081E0000, // - 0x081FFFFF | 128 KiB
- [24] = 0x08200000, // last element - not a valid sector
-#elif defined STM32U585xx || defined STM32U5G9xx
- [0] = 0x08000000, // - 0x08001FFF | 8 KiB
- // rest is initialized in flash_init
-#else
-#error Unknown MCU
-#endif
-};
-
-static uint8_t *FLASH_BUFFER = NULL;
-static uint32_t FLASH_SIZE;
-
-static void flash_exit(void) {
- int r = munmap(FLASH_BUFFER, FLASH_SIZE);
- ensure(sectrue * (r == 0), "munmap failed");
-}
-
-void flash_init(void) {
- if (FLASH_BUFFER) return;
-
-#if defined STM32U585xx || defined STM32U5G9xx
- for (size_t i = 0; i < FLASH_SECTOR_COUNT; i++) {
- FLASH_SECTOR_TABLE[i + 1] =
- FLASH_SECTOR_TABLE[i] + 0x2000; // 8KiB size sectors
- }
-#endif
-
- FLASH_SIZE = FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT] - FLASH_SECTOR_TABLE[0];
-
- // check whether the file exists and it has the correct size
- struct stat sb;
- int r = stat(FLASH_FILE, &sb);
-
- // (re)create if non existent or wrong size
- if (r != 0 || sb.st_size != FLASH_SIZE) {
- int fd = open(FLASH_FILE, O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
- ensure(sectrue * (fd >= 0), "open failed");
- for (int i = 0; i < FLASH_SIZE / 16; i++) {
- ssize_t s = write(
- fd,
- "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
- 16);
- ensure(sectrue * (s >= 0), "write failed");
- }
- r = close(fd);
- ensure(sectrue * (r == 0), "close failed");
- }
-
- // mmap file
- int fd = open(FLASH_FILE, O_RDWR);
- ensure(sectrue * (fd >= 0), "open failed");
-
- void *map = mmap(0, FLASH_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- ensure(sectrue * (map != MAP_FAILED), "mmap failed");
-
- FLASH_BUFFER = (uint8_t *)map;
-
- atexit(flash_exit);
-}
-
-secbool flash_unlock_write(void) { return sectrue; }
-
-secbool flash_lock_write(void) { return sectrue; }
-
-const void *flash_get_address(uint16_t sector, uint32_t offset, uint32_t size) {
- if (sector >= FLASH_SECTOR_COUNT) {
- return NULL;
- }
- const uint32_t addr = FLASH_SECTOR_TABLE[sector] + offset;
- const uint32_t next = FLASH_SECTOR_TABLE[sector + 1];
- if (addr + size > next) {
- return NULL;
- }
- return FLASH_BUFFER + addr - FLASH_SECTOR_TABLE[0];
-}
-
-uint32_t flash_sector_size(uint16_t first_sector, uint16_t sector_count) {
- if (first_sector + sector_count > FLASH_SECTOR_COUNT) {
- return 0;
- }
- return FLASH_SECTOR_TABLE[first_sector + sector_count] -
- FLASH_SECTOR_TABLE[first_sector];
-}
-
-uint16_t flash_sector_find(uint16_t first_sector, uint32_t offset) {
- uint16_t sector = first_sector;
-
- while (sector < FLASH_SECTOR_COUNT) {
- uint32_t sector_size =
- FLASH_SECTOR_TABLE[sector + 1] - FLASH_SECTOR_TABLE[sector];
-
- if (offset < sector_size) {
- break;
- }
- offset -= sector_size;
- sector++;
- }
-
- return sector;
-}
-
-secbool flash_sector_erase(uint16_t sector) {
- if (sector >= FLASH_SECTOR_COUNT) {
- return secfalse;
- }
-
- 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);
-
- return sectrue;
-}
-
-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;
- }
- if ((flash[0] & data) != data) {
- return secfalse; // we cannot change zeroes to ones
- }
- flash[0] = data;
- return sectrue;
-}
-
-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;
- }
- uint32_t *flash = (uint32_t *)flash_get_address(sector, offset, sizeof(data));
- if (!flash) {
- return secfalse;
- }
- if ((flash[0] & data) != data) {
- return secfalse; // we cannot change zeroes to ones
- }
- flash[0] = data;
- return sectrue;
-}
-
-secbool flash_write_block(uint16_t sector, uint32_t offset,
- const flash_block_t block) {
- if (offset % (sizeof(uint32_t) *
- FLASH_BLOCK_WORDS)) { // we write only at block boundary
- return secfalse;
- }
-
- for (int i = 0; i < FLASH_BLOCK_WORDS; i++) {
- if (!flash_write_word(sector, offset + i * sizeof(uint32_t), block[i])) {
- return secfalse;
- }
- }
- return sectrue;
-}
diff --git a/core/embed/util/flash/unix/flash_otp.c b/core/embed/util/flash/unix/flash_otp.c
deleted file mode 100644
index 3eecc0ea..00000000
--- a/core/embed/util/flash/unix/flash_otp.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <trezor_rtl.h>
-
-#include <util/flash_otp.h>
-
-#define OTP_BLOCK_SIZE 32
-#define FLASH_SECTOR_OTP (FLASH_SECTOR_COUNT)
-
-static uint8_t OTP_BUFFER[OTP_BLOCK_SIZE * 64];
-
-void flash_otp_init(void) {
- // fill OTP buffer with ones
- memset(OTP_BUFFER, 0xFF, sizeof(OTP_BUFFER));
-}
-
-secbool flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data,
- uint8_t datalen) {
- if (offset + datalen > OTP_BLOCK_SIZE) {
- return secfalse;
- }
- uint32_t offset_in_sector = block * OTP_BLOCK_SIZE + offset;
- memcpy(data, OTP_BUFFER + offset_in_sector, datalen);
- return sectrue;
-}
-
-secbool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data,
- uint8_t datalen) {
- if (offset + datalen > OTP_BLOCK_SIZE) {
- return secfalse;
- }
- uint32_t offset_in_sector = block * OTP_BLOCK_SIZE + offset;
- uint8_t *flash = OTP_BUFFER + offset_in_sector;
- for (int i = 0; i < datalen; i++) {
- if ((flash[i] & data[i]) != data[i]) {
- return secfalse; // we cannot change zeroes to ones
- }
- flash[i] = data[i];
- }
- return sectrue;
-}
-
-secbool flash_otp_lock(uint8_t block) { return secfalse; }
-
-secbool flash_otp_is_locked(uint8_t block) { return secfalse; }
diff --git a/core/embed/util/fwutils/fwutils.c b/core/embed/util/fwutils/fwutils.c
index 15801cad..5bc4df0a 100644
--- a/core/embed/util/fwutils/fwutils.c
+++ b/core/embed/util/fwutils/fwutils.c
@@ -23,8 +23,8 @@
#include <trezor_model.h>
#include <trezor_rtl.h>
+#include <sys/flash.h>
#include <sys/systask.h>
-#include <util/flash.h>
#include <util/fwutils.h>
#include <util/image.h>
diff --git a/core/embed/util/image/boot_image.c b/core/embed/util/image/boot_image.c
index ada0676f..dd420cb7 100644
--- a/core/embed/util/image/boot_image.c
+++ b/core/embed/util/image/boot_image.c
@@ -24,9 +24,9 @@
#include <sec/board_capabilities.h>
#include <sec/monoctr.h>
+#include <sys/flash.h>
#include <sys/mpu.h>
#include <util/boot_image.h>
-#include <util/flash.h>
#include <util/image.h>
#include "blake2s.h"
diff --git a/core/embed/util/image/boot_ucb.c b/core/embed/util/image/boot_ucb.c
index 0c4fb643..7c8b909c 100644
--- a/core/embed/util/image/boot_ucb.c
+++ b/core/embed/util/image/boot_ucb.c
@@ -24,10 +24,10 @@
#include <trezor_rtl.h>
#include <rtl/sizedefs.h>
+#include <sys/flash.h>
#include <sys/mpu.h>
#include <util/boot_header.h>
#include <util/boot_ucb.h>
-#include <util/flash.h>
#include <util/image_hash_conf.h>
#define BOOT_UCB_MAGIC 0x5A8C7BF3
diff --git a/core/embed/util/image/image.c b/core/embed/util/image/image.c
index 5d03214c..a2c52d7f 100644
--- a/core/embed/util/image/image.c
+++ b/core/embed/util/image/image.c
@@ -23,7 +23,7 @@
#include "ed25519-donna/ed25519.h"
#include <sys/bootutils.h>
-#include <util/flash.h>
+#include <sys/flash.h>
#include <util/image.h>
#ifdef STM32F4
diff --git a/core/embed/util/image/inc/util/image.h b/core/embed/util/image/inc/util/image.h
index 6b7e3cb5..4b92b132 100644
--- a/core/embed/util/image/inc/util/image.h
+++ b/core/embed/util/image/inc/util/image.h
@@ -22,7 +22,7 @@
#include <trezor_model.h>
#include <trezor_types.h>
-#include <util/flash.h>
+#include <sys/flash.h>
#include "blake2s.h"
#include "image_hash_conf.h"
diff --git a/core/embed/util/translations/translations.c b/core/embed/util/translations/translations.c
index 4fcac4cb..4bebf41c 100644
--- a/core/embed/util/translations/translations.c
+++ b/core/embed/util/translations/translations.c
@@ -22,8 +22,8 @@
#include <trezor_model.h>
#include <trezor_rtl.h>
+#include <sys/flash.h>
#include <sys/mpu.h>
-#include <util/flash.h>
#include <util/translations.h>
bool translations_write(const uint8_t* data, uint32_t offset, uint32_t len) {
diff --git a/core/site_scons/models/T2B1/emulator.py b/core/site_scons/models/T2B1/emulator.py
index 150ff854..9087f0ed 100644
--- a/core/site_scons/models/T2B1/emulator.py
+++ b/core/site_scons/models/T2B1/emulator.py
@@ -61,6 +61,6 @@ def configure(
features_available.append("button")
defines += [("USE_BUTTON", "1")]
- sources += ["embed/util/flash/stm32f4/flash_layout.c"]
+ sources += ["embed/sys/flash/stm32f4/flash_layout.c"]
return features_available
diff --git a/core/site_scons/models/T2T1/emulator.py b/core/site_scons/models/T2T1/emulator.py
index 9cca37bd..3b2a6f67 100644
--- a/core/site_scons/models/T2T1/emulator.py
+++ b/core/site_scons/models/T2T1/emulator.py
@@ -65,6 +65,6 @@ def configure(
features_available.append("backlight")
defines += [("USE_BACKLIGHT", "1")]
- sources += ["embed/util/flash/stm32f4/flash_layout.c"]
+ sources += ["embed/sys/flash/stm32f4/flash_layout.c"]
return features_available
diff --git a/core/site_scons/models/T3B1/emulator.py b/core/site_scons/models/T3B1/emulator.py
index e144cdb7..20161095 100644
--- a/core/site_scons/models/T3B1/emulator.py
+++ b/core/site_scons/models/T3B1/emulator.py
@@ -61,6 +61,6 @@ def configure(
features_available.append("button")
defines += [("USE_BUTTON", "1")]
- sources += ["embed/util/flash/stm32u5/flash_layout.c"]
+ sources += ["embed/sys/flash/stm32u5/flash_layout.c"]
return features_available
diff --git a/core/site_scons/models/T3T1/emulator.py b/core/site_scons/models/T3T1/emulator.py
index cd757521..7b398366 100644
--- a/core/site_scons/models/T3T1/emulator.py
+++ b/core/site_scons/models/T3T1/emulator.py
@@ -76,6 +76,6 @@ def configure(
features_available.append("backlight")
defines += [("USE_BACKLIGHT", "1")]
- sources += ["embed/util/flash/stm32u5/flash_layout.c"]
+ sources += ["embed/sys/flash/stm32u5/flash_layout.c"]
return features_available
diff --git a/core/site_scons/models/T3W1/emulator.py b/core/site_scons/models/T3W1/emulator.py
index 77f2fad3..f5b4acb3 100644
--- a/core/site_scons/models/T3W1/emulator.py
+++ b/core/site_scons/models/T3W1/emulator.py
@@ -130,7 +130,7 @@ def configure(
features_available.append("backlight")
defines += [("USE_BACKLIGHT", "1")]
- sources += ["embed/util/flash/stm32u5/flash_layout.c"]
+ sources += ["embed/sys/flash/stm32u5/flash_layout.c"]
defines += ["USE_HW_JPEG_DECODER"]
features_available.append("hw_jpeg_decoder")
diff --git a/core/site_scons/models/stm32f4_common.py b/core/site_scons/models/stm32f4_common.py
index acccc6b9..1debc734 100644
--- a/core/site_scons/models/stm32f4_common.py
+++ b/core/site_scons/models/stm32f4_common.py
@@ -30,12 +30,12 @@ def stm32f4_common_files(env, features_wanted, defines, sources, paths):
"embed/sec/board_capabilities/inc",
"embed/sec/secret/inc",
"embed/sec/unit_properties/inc",
+ "embed/sys/flash/inc",
"embed/sys/stack/inc",
"embed/sys/startup/inc",
"embed/sys/syscall/inc",
"embed/sys/task/inc",
"embed/sys/time/inc",
- "embed/util/flash/inc",
"embed/util/fwutils/inc",
"vendor/micropython/lib/cmsis/inc",
"vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Inc",
@@ -80,6 +80,9 @@ def stm32f4_common_files(env, features_wanted, defines, sources, paths):
"embed/sec/time_estimate/stm32/time_estimate.c",
"embed/sec/unit_properties/stm32/unit_properties.c",
"embed/sys/cpuid/stm32/cpuid.c",
+ "embed/sys/flash/stm32f4/flash.c",
+ "embed/sys/flash/stm32f4/flash_layout.c",
+ "embed/sys/flash/stm32f4/flash_otp.c",
"embed/sys/irq/stm32/irq.c",
"embed/sys/linker/linker_utils.c",
"embed/sys/mpu/stm32f4/mpu.c",
@@ -104,9 +107,6 @@ def stm32f4_common_files(env, features_wanted, defines, sources, paths):
"embed/sys/time/stm32/systick.c",
"embed/sys/time/stm32/systimer.c",
"embed/sys/task/sysevent.c",
- "embed/util/flash/stm32f4/flash.c",
- "embed/util/flash/stm32f4/flash_layout.c",
- "embed/util/flash/stm32f4/flash_otp.c",
"embed/util/fwutils/fwutils.c",
]
diff --git a/core/site_scons/models/stm32u5_common.py b/core/site_scons/models/stm32u5_common.py
index 04f83de6..d54c3f67 100644
--- a/core/site_scons/models/stm32u5_common.py
+++ b/core/site_scons/models/stm32u5_common.py
@@ -28,6 +28,7 @@ def stm32u5_common_files(env, features_wanted, defines, sources, paths):
"embed/sys/cpuid/inc",
"embed/sys/inc",
"embed/sys/irq/inc",
+ "embed/sys/flash/inc",
"embed/sys/linker/inc",
"embed/sys/mpu/inc",
"embed/sys/pvd/inc",
@@ -38,7 +39,6 @@ def stm32u5_common_files(env, features_wanted, defines, sources, paths):
"embed/sys/task/inc",
"embed/sys/time/inc",
"embed/sys/trustzone/inc",
- "embed/util/flash/inc",
"embed/util/fwutils/inc",
"vendor/stm32u5xx_hal_driver/Inc",
"vendor/cmsis_device_u5/Include",
@@ -106,6 +106,9 @@ def stm32u5_common_files(env, features_wanted, defines, sources, paths):
"embed/sec/time_estimate/stm32/time_estimate.c",
"embed/sec/unit_properties/stm32/unit_properties.c",
"embed/sys/cpuid/stm32/cpuid.c",
+ "embed/sys/flash/stm32u5/flash.c",
+ "embed/sys/flash/stm32u5/flash_layout.c",
+ "embed/sys/flash/stm32u5/flash_otp.c",
"embed/sys/irq/stm32/irq.c",
"embed/sys/linker/linker_utils.c",
"embed/sys/mpu/stm32u5/mpu.c",
@@ -133,9 +136,6 @@ def stm32u5_common_files(env, features_wanted, defines, sources, paths):
"embed/sys/time/stm32/systimer.c",
"embed/sys/task/sysevent.c",
"embed/sys/trustzone/stm32u5/trustzone.c",
- "embed/util/flash/stm32u5/flash.c",
- "embed/util/flash/stm32u5/flash_layout.c",
- "embed/util/flash/stm32u5/flash_otp.c",
"embed/util/fwutils/fwutils.c",
]
diff --git a/core/site_scons/models/unix_common.py b/core/site_scons/models/unix_common.py
index 5cfcff30..bed1fa5c 100644
--- a/core/site_scons/models/unix_common.py
+++ b/core/site_scons/models/unix_common.py
@@ -22,13 +22,13 @@ def unix_common_files(env, features_wanted, defines, sources, paths):
"embed/sec/secret/inc",
"embed/sec/unit_properties/inc",
"embed/sys/cpuid/inc",
+ "embed/sys/flash/inc",
"embed/sys/irq/inc",
"embed/sys/mpu/inc",
"embed/sys/rng/inc",
"embed/sys/startup/inc",
"embed/sys/task/inc",
"embed/sys/time/inc",
- "embed/util/flash/inc",
"embed/util/fwutils/inc",
]
@@ -47,6 +47,8 @@ def unix_common_files(env, features_wanted, defines, sources, paths):
"embed/sec/time_estimate/unix/time_estimate.c",
"embed/sec/unit_properties/unix/unit_properties.c",
"embed/sys/cpuid/unix/cpuid.c",
+ "embed/sys/flash/unix/flash.c",
+ "embed/sys/flash/unix/flash_otp.c",
"embed/sys/mpu/unix/mpu.c",
"embed/sys/rng/unix/rng.c",
"embed/sys/startup/unix/bootutils.c",
@@ -56,8 +58,6 @@ def unix_common_files(env, features_wanted, defines, sources, paths):
"embed/sys/task/unix/systask.c",
"embed/sys/time/unix/systick.c",
"embed/sys/time/unix/systimer.c",
- "embed/util/flash/unix/flash.c",
- "embed/util/flash/unix/flash_otp.c",
"embed/util/fwutils/fwutils.c",
]
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.