diff --git a/core/embed/prodtest/main.c b/core/embed/prodtest/main.c
index 4712891ef7..66114bfe7c 100644
--- a/core/embed/prodtest/main.c
+++ b/core/embed/prodtest/main.c
@@ -34,6 +34,7 @@
#include "fault_handlers.h"
#include "flash.h"
#include "flash_otp.h"
+#include "fwutils.h"
#include "i2c.h"
#include "image.h"
#include "model.h"
diff --git a/core/embed/trezorhal/common.h b/core/embed/trezorhal/common.h
index 457950dd46..6756030dd6 100644
--- a/core/embed/trezorhal/common.h
+++ b/core/embed/trezorhal/common.h
@@ -53,8 +53,4 @@
})
#endif
-// Invalidates firmware on the device
-// Note: only works when write access to firmware area is enabled by MPU
-void invalidate_firmware(void);
-
#endif
diff --git a/core/embed/trezorhal/fwutils.h b/core/embed/trezorhal/fwutils.h
new file mode 100644
index 0000000000..26e484c8ff
--- /dev/null
+++ b/core/embed/trezorhal/fwutils.h
@@ -0,0 +1,28 @@
+/*
+ * 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 .
+ */
+
+#ifndef TREZORHAL_FWUTILS_H
+#define TREZORHAL_FWUTILS_H
+
+// Invalidates the firmware by erasing the first 1KB of the firmware area.
+//
+// Note: only works when write access to firmware area is enabled by MPU
+void invalidate_firmware(void);
+
+#endif // TREZORHAL_FWUTILS_H
diff --git a/core/embed/trezorhal/stm32f4/common.c b/core/embed/trezorhal/stm32f4/common.c
index 339de06384..17395f7208 100644
--- a/core/embed/trezorhal/stm32f4/common.c
+++ b/core/embed/trezorhal/stm32f4/common.c
@@ -52,14 +52,3 @@ void clear_otg_hs_memory(void) {
__HAL_RCC_USB_OTG_HS_CLK_DISABLE(); // disable USB OTG_HS peripheral clock as
// the peripheral is not needed right now
}
-
-void invalidate_firmware(void) {
- // erase start of the firmware (metadata) -> invalidate FW
- ensure(flash_unlock_write(), NULL);
- for (int i = 0; i < (1024 / FLASH_BLOCK_SIZE); i += FLASH_BLOCK_SIZE) {
- flash_block_t data = {0};
- ensure(flash_area_write_block(&FIRMWARE_AREA, i * FLASH_BLOCK_SIZE, data),
- NULL);
- }
- ensure(flash_lock_write(), NULL);
-}
diff --git a/core/embed/trezorhal/stm32f4/fwutils.c b/core/embed/trezorhal/stm32f4/fwutils.c
new file mode 100644
index 0000000000..1d5990e117
--- /dev/null
+++ b/core/embed/trezorhal/stm32f4/fwutils.c
@@ -0,0 +1,43 @@
+/*
+ * 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 .
+ */
+
+#include STM32_HAL_H
+
+#include "fwutils.h"
+#include "error_handling.h"
+#include "flash.h"
+#include "flash_area.h"
+#include "model.h"
+
+void invalidate_firmware(void) {
+#ifdef STM32U5
+ // on stm32u5, we need to disable the instruction cache before erasing the
+ // firmware - otherwise, the write check will fail
+ ICACHE->CR &= ~ICACHE_CR_EN;
+#endif
+
+ // erase start of the firmware (metadata) -> invalidate FW
+ ensure(flash_unlock_write(), NULL);
+ for (int i = 0; i < (1024 / FLASH_BLOCK_SIZE); i += FLASH_BLOCK_SIZE) {
+ flash_block_t data = {0};
+ ensure(flash_area_write_block(&FIRMWARE_AREA, i * FLASH_BLOCK_SIZE, data),
+ NULL);
+ }
+ ensure(flash_lock_write(), NULL);
+}
diff --git a/core/embed/trezorhal/stm32u5/common.c b/core/embed/trezorhal/stm32u5/common.c
index abf3d943f6..5efbb40887 100644
--- a/core/embed/trezorhal/stm32u5/common.c
+++ b/core/embed/trezorhal/stm32u5/common.c
@@ -31,18 +31,3 @@
#include "secret.h"
#include "stm32u5xx_ll_utils.h"
-
-void invalidate_firmware(void) {
- // on stm32u5, we need to disable the instruction cache before erasing the
- // firmware - otherwise, the write check will fail
- ICACHE->CR &= ~ICACHE_CR_EN;
-
- // erase start of the firmware (metadata) -> invalidate FW
- ensure(flash_unlock_write(), NULL);
- for (int i = 0; i < (1024 / FLASH_BLOCK_SIZE); i += FLASH_BLOCK_SIZE) {
- flash_block_t data = {0};
- ensure(flash_area_write_block(&FIRMWARE_AREA, i * FLASH_BLOCK_SIZE, data),
- NULL);
- }
- ensure(flash_lock_write(), NULL);
-}
diff --git a/core/embed/trezorhal/stm32u5/fwutils.c b/core/embed/trezorhal/stm32u5/fwutils.c
new file mode 120000
index 0000000000..8968a5a024
--- /dev/null
+++ b/core/embed/trezorhal/stm32u5/fwutils.c
@@ -0,0 +1 @@
+../stm32f4/fwutils.c
\ No newline at end of file
diff --git a/core/site_scons/models/stm32f4_common.py b/core/site_scons/models/stm32f4_common.py
index 3c41945047..b778ea860d 100644
--- a/core/site_scons/models/stm32f4_common.py
+++ b/core/site_scons/models/stm32f4_common.py
@@ -47,6 +47,7 @@ def stm32f4_common_files(env, defines, sources, paths):
"embed/trezorhal/stm32f4/fault_handlers.c",
"embed/trezorhal/stm32f4/flash.c",
"embed/trezorhal/stm32f4/flash_otp.c",
+ "embed/trezorhal/stm32f4/fwutils.c",
"embed/trezorhal/stm32f4/lowlevel.c",
"embed/trezorhal/stm32f4/monoctr.c",
"embed/trezorhal/stm32f4/mpu.c",
diff --git a/core/site_scons/models/stm32u5_common.py b/core/site_scons/models/stm32u5_common.py
index 123f904fe9..7d9c465673 100644
--- a/core/site_scons/models/stm32u5_common.py
+++ b/core/site_scons/models/stm32u5_common.py
@@ -56,6 +56,7 @@ def stm32u5_common_files(env, defines, sources, paths):
"embed/trezorhal/stm32u5/fault_handlers.c",
"embed/trezorhal/stm32u5/flash.c",
"embed/trezorhal/stm32u5/flash_otp.c",
+ "embed/trezorhal/stm32u5/fwutils.c",
"embed/trezorhal/stm32u5/lowlevel.c",
"embed/trezorhal/stm32u5/hash_processor.c",
"embed/trezorhal/stm32u5/monoctr.c",