1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-19 05:58:09 +00:00

refactor(core/embed): introduce new mpu driver

[no changelog]
This commit is contained in:
cepetr 2024-09-07 13:50:10 +02:00 committed by cepetr
parent 8fab22522a
commit 7f3cff04f1
41 changed files with 935 additions and 509 deletions

View File

@ -69,6 +69,7 @@ SOURCE_MOD += [
'embed/lib/colors.c', 'embed/lib/colors.c',
'embed/lib/display_utils.c', 'embed/lib/display_utils.c',
'embed/lib/error_handling.c', 'embed/lib/error_handling.c',
'embed/lib/flash_utils.c',
'embed/lib/fonts/font_bitmap.c', 'embed/lib/fonts/font_bitmap.c',
'embed/lib/fonts/fonts.c', 'embed/lib/fonts/fonts.c',
'embed/lib/gfx_color.c', 'embed/lib/gfx_color.c',

View File

@ -108,6 +108,7 @@ SOURCE_MOD += [
'embed/lib/colors.c', 'embed/lib/colors.c',
'embed/lib/display_utils.c', 'embed/lib/display_utils.c',
'embed/lib/error_handling.c', 'embed/lib/error_handling.c',
'embed/lib/flash_utils.c',
'embed/lib/fonts/font_bitmap.c', 'embed/lib/fonts/font_bitmap.c',
'embed/lib/fonts/fonts.c', 'embed/lib/fonts/fonts.c',
'embed/lib/gfx_color.c', 'embed/lib/gfx_color.c',

View File

@ -101,6 +101,7 @@ SOURCE_MOD += [
'embed/lib/colors.c', 'embed/lib/colors.c',
'embed/lib/display_utils.c', 'embed/lib/display_utils.c',
'embed/lib/error_handling.c', 'embed/lib/error_handling.c',
'embed/lib/flash_utils.c',
'embed/lib/fonts/font_bitmap.c', 'embed/lib/fonts/font_bitmap.c',
'embed/lib/fonts/fonts.c', 'embed/lib/fonts/fonts.c',
'embed/lib/gfx_color.c', 'embed/lib/gfx_color.c',

View File

@ -103,6 +103,7 @@ SOURCE_MOD += [
'embed/lib/colors.c', 'embed/lib/colors.c',
'embed/lib/display_utils.c', 'embed/lib/display_utils.c',
'embed/lib/error_handling.c', 'embed/lib/error_handling.c',
'embed/lib/flash_utils.c',
'embed/lib/fonts/font_bitmap.c', 'embed/lib/fonts/font_bitmap.c',
'embed/lib/fonts/fonts.c', 'embed/lib/fonts/fonts.c',
'embed/lib/gfx_color.c', 'embed/lib/gfx_color.c',
@ -150,6 +151,7 @@ SOURCE_TREZORHAL = [
'embed/trezorhal/unix/fault_handlers.c', 'embed/trezorhal/unix/fault_handlers.c',
'embed/trezorhal/unix/flash.c', 'embed/trezorhal/unix/flash.c',
'embed/trezorhal/unix/flash_otp.c', 'embed/trezorhal/unix/flash_otp.c',
'embed/trezorhal/unix/mpu.c',
'embed/trezorhal/unix/monoctr.c', 'embed/trezorhal/unix/monoctr.c',
'embed/trezorhal/unix/random_delays.c', 'embed/trezorhal/unix/random_delays.c',
'embed/trezorhal/unix/rng.c', 'embed/trezorhal/unix/rng.c',

View File

@ -228,6 +228,7 @@ SOURCE_MOD += [
'embed/lib/colors.c', 'embed/lib/colors.c',
'embed/lib/display_utils.c', 'embed/lib/display_utils.c',
'embed/lib/error_handling.c', 'embed/lib/error_handling.c',
'embed/lib/flash_utils.c',
'embed/lib/fonts/font_bitmap.c', 'embed/lib/fonts/font_bitmap.c',
'embed/lib/fonts/fonts.c', 'embed/lib/fonts/fonts.c',
'embed/lib/gfx_color.c', 'embed/lib/gfx_color.c',

View File

@ -423,6 +423,7 @@ SOURCE_UNIX = [
'embed/trezorhal/unix/flash_otp.c', 'embed/trezorhal/unix/flash_otp.c',
'embed/trezorhal/unix/flash.c', 'embed/trezorhal/unix/flash.c',
'embed/trezorhal/unix/fwutils.c', 'embed/trezorhal/unix/fwutils.c',
'embed/trezorhal/unix/mpu.c',
'embed/trezorhal/unix/random_delays.c', 'embed/trezorhal/unix/random_delays.c',
'embed/trezorhal/unix/rng.c', 'embed/trezorhal/unix/rng.c',
'embed/trezorhal/unix/systick.c', 'embed/trezorhal/unix/systick.c',

View File

@ -28,6 +28,7 @@
#include "display_draw.h" #include "display_draw.h"
#include "fault_handlers.h" #include "fault_handlers.h"
#include "flash.h" #include "flash.h"
#include "flash_utils.h"
#include "image.h" #include "image.h"
#include "model.h" #include "model.h"
#include "mpu.h" #include "mpu.h"
@ -208,7 +209,7 @@ static secbool copy_sdcard(void) {
term_printf("\n\nerasing flash:\n\n"); term_printf("\n\nerasing flash:\n\n");
// erase all flash (except boardloader) // erase all flash (except boardloader)
if (sectrue != flash_area_erase(&ALL_WIPE_AREA, progress_callback)) { if (sectrue != erase_device(progress_callback)) {
term_printf(" failed\n"); term_printf(" failed\n");
return secfalse; return secfalse;
} }
@ -244,9 +245,7 @@ int main(void) {
if (sectrue != flash_configure_option_bytes()) { if (sectrue != flash_configure_option_bytes()) {
// display is not initialized so don't call ensure // display is not initialized so don't call ensure
const secbool r = erase_storage(NULL);
flash_area_erase_bulk(STORAGE_AREAS, STORAGE_AREAS_COUNT, NULL);
(void)r;
return 2; return 2;
} }
@ -262,8 +261,6 @@ int main(void) {
clear_otg_hs_memory(); clear_otg_hs_memory();
#endif #endif
mpu_config_boardloader();
fault_handlers_init(); fault_handlers_init();
#ifdef USE_SDRAM #ifdef USE_SDRAM
@ -335,7 +332,7 @@ int main(void) {
ensure_compatible_settings(); ensure_compatible_settings();
#endif #endif
mpu_config_off(); mpu_reconfig(MPU_MODE_DISABLED);
// g_boot_command is preserved on STM32U5 // g_boot_command is preserved on STM32U5
jump_to(IMAGE_CODE_ALIGN(BOOTLOADER_START + IMAGE_HEADER_SIZE)); jump_to(IMAGE_CODE_ALIGN(BOOTLOADER_START + IMAGE_HEADER_SIZE));

View File

@ -170,10 +170,6 @@ __attribute__((noreturn)) int main(int argc, char **argv) {
jump_to(0); jump_to(0);
} }
void mpu_config_bootloader(void) {}
void mpu_config_off(void) {}
void jump_to(uint32_t address) { void jump_to(uint32_t address) {
bool storage_is_erased = bool storage_is_erased =
storage_empty(&STORAGE_AREAS[0]) && storage_empty(&STORAGE_AREAS[1]); storage_empty(&STORAGE_AREAS[0]) && storage_empty(&STORAGE_AREAS[1]);

View File

@ -13,8 +13,6 @@ extern uint8_t *FIRMWARE_START;
void emulator_poll_events(void); void emulator_poll_events(void);
void set_core_clock(int); void set_core_clock(int);
void mpu_config_bootloader(void);
void mpu_config_off(void);
__attribute__((noreturn)) void jump_to(uint32_t address); __attribute__((noreturn)) void jump_to(uint32_t address);
#endif #endif

View File

@ -28,6 +28,7 @@
#include "fault_handlers.h" #include "fault_handlers.h"
#include "flash.h" #include "flash.h"
#include "flash_otp.h" #include "flash_otp.h"
#include "flash_utils.h"
#include "image.h" #include "image.h"
#include "lowlevel.h" #include "lowlevel.h"
#include "messages.pb.h" #include "messages.pb.h"
@ -335,7 +336,8 @@ void real_jump_to_firmware(void) {
ensure_compatible_settings(); ensure_compatible_settings();
#endif #endif
mpu_config_off(); mpu_reconfig(MPU_MODE_DISABLED);
jump_to(IMAGE_CODE_ALIGN(FIRMWARE_START + vhdr.hdrlen + IMAGE_HEADER_SIZE)); jump_to(IMAGE_CODE_ALIGN(FIRMWARE_START + vhdr.hdrlen + IMAGE_HEADER_SIZE));
} }
@ -394,8 +396,6 @@ int bootloader_main(void) {
ui_screen_boot_stage_1(false); ui_screen_boot_stage_1(false);
mpu_config_bootloader();
fault_handlers_init(); fault_handlers_init();
#ifdef TREZOR_EMULATOR #ifdef TREZOR_EMULATOR
@ -559,9 +559,7 @@ int bootloader_main(void) {
#ifdef STM32U5 #ifdef STM32U5
secret_bhk_regenerate(); secret_bhk_regenerate();
#endif #endif
// erase storage ensure(erase_storage(NULL), NULL);
ensure(flash_area_erase_bulk(STORAGE_AREAS, STORAGE_AREAS_COUNT, NULL),
NULL);
// keep the model screen up for a while // keep the model screen up for a while
#ifndef USE_BACKLIGHT #ifndef USE_BACKLIGHT
@ -669,8 +667,7 @@ int bootloader_main(void) {
#ifdef STM32U5 #ifdef STM32U5
secret_bhk_regenerate(); secret_bhk_regenerate();
#endif #endif
ensure(flash_area_erase_bulk(STORAGE_AREAS, STORAGE_AREAS_COUNT, NULL), ensure(erase_storage(NULL), NULL);
NULL);
} }
ensure(dont_optimize_out_true * ensure(dont_optimize_out_true *
(continue_to_firmware == continue_to_firmware_backup), (continue_to_firmware == continue_to_firmware_backup),

View File

@ -27,6 +27,7 @@
#include "bootargs.h" #include "bootargs.h"
#include "common.h" #include "common.h"
#include "flash.h" #include "flash.h"
#include "flash_utils.h"
#include "image.h" #include "image.h"
#include "secbool.h" #include "secbool.h"
#include "secret.h" #include "secret.h"
@ -715,8 +716,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
#ifdef STM32U5 #ifdef STM32U5
secret_bhk_regenerate(); secret_bhk_regenerate();
#endif #endif
ensure(flash_area_erase_bulk(STORAGE_AREAS, STORAGE_AREAS_COUNT, NULL), ensure(erase_storage(NULL), NULL);
NULL);
} }
headers_offset = IMAGE_CODE_ALIGN(IMAGE_HEADER_SIZE + vhdr.hdrlen); headers_offset = IMAGE_CODE_ALIGN(IMAGE_HEADER_SIZE + vhdr.hdrlen);
@ -840,7 +840,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
} }
secbool bootloader_WipeDevice(void) { secbool bootloader_WipeDevice(void) {
return flash_area_erase(&WIPE_AREA, ui_screen_wipe_progress); return erase_device(ui_screen_wipe_progress);
} }
int process_msg_WipeDevice(uint8_t iface_num, uint32_t msg_size, uint8_t *buf) { int process_msg_WipeDevice(uint8_t iface_num, uint32_t msg_size, uint8_t *buf) {

View File

@ -188,8 +188,6 @@ int main(void) {
hash_processor_init(); hash_processor_init();
#endif #endif
mpu_config_bootloader();
#if PRODUCTION && !defined STM32U5 #if PRODUCTION && !defined STM32U5
// for STM32U5, this check is moved to boardloader // for STM32U5, this check is moved to boardloader
ensure_bootloader_min_version(); ensure_bootloader_min_version();
@ -270,7 +268,8 @@ int main(void) {
// do not check any trust flags on header, proceed // do not check any trust flags on header, proceed
mpu_config_off(); mpu_reconfig(MPU_MODE_DISABLED);
jump_to(IMAGE_CODE_ALIGN(FIRMWARE_START + vhdr.hdrlen + IMAGE_HEADER_SIZE)); jump_to(IMAGE_CODE_ALIGN(FIRMWARE_START + vhdr.hdrlen + IMAGE_HEADER_SIZE));
return 0; return 0;

View File

@ -26,6 +26,7 @@
#include "common.h" #include "common.h"
#include "flash.h" #include "flash.h"
#include "flash_utils.h"
#include "image.h" #include "image.h"
#include "model.h" #include "model.h"
#include "secbool.h" #include "secbool.h"
@ -648,14 +649,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
} }
int process_msg_WipeDevice(uint8_t iface_num, uint32_t msg_size, uint8_t *buf) { int process_msg_WipeDevice(uint8_t iface_num, uint32_t msg_size, uint8_t *buf) {
flash_area_t wipe_area[STORAGE_AREAS_COUNT + 1]; if (sectrue != erase_device(ui_screen_wipe_progress)) {
for (int i = 0; i < STORAGE_AREAS_COUNT; i++) {
memcpy(&wipe_area[i], &STORAGE_AREAS[i], sizeof(flash_area_t));
}
memcpy(&wipe_area[STORAGE_AREAS_COUNT], &FIRMWARE_AREA, sizeof(flash_area_t));
if (sectrue != flash_area_erase_bulk(wipe_area, STORAGE_AREAS_COUNT + 1,
ui_screen_wipe_progress)) {
MSG_SEND_INIT(Failure); MSG_SEND_INIT(Failure);
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError); MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Could not erase flash"); MSG_SEND_ASSIGN_STRING(message, "Could not erase flash");

View File

@ -173,15 +173,12 @@ int main(void) {
secbool secret_ok = secret_optiga_get(secret); secbool secret_ok = secret_optiga_get(secret);
#endif #endif
mpu_config_firmware_initial();
entropy_init(); entropy_init();
#if PRODUCTION || BOOTLOADER_QA #if PRODUCTION || BOOTLOADER_QA
check_and_replace_bootloader(); check_and_replace_bootloader();
#endif #endif
// Enable MPU
mpu_config_firmware();
#endif #endif
// Init peripherals // Init peripherals

View File

@ -0,0 +1,105 @@
/*
* 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_BOARD
#include "flash_utils.h"
#include "common.h"
#include "flash_area.h"
#include "model.h"
#include "mpu.h"
#include "secbool.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 = &TRANSLATIONS_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);
}

View File

@ -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 "secbool.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

View File

@ -5,6 +5,7 @@
#include "common.h" #include "common.h"
#include "flash.h" #include "flash.h"
#include "model.h" #include "model.h"
#include "mpu.h"
bool translations_write(const uint8_t* data, uint32_t offset, uint32_t len) { bool translations_write(const uint8_t* data, uint32_t offset, uint32_t len) {
uint32_t size = translations_area_bytesize(); uint32_t size = translations_area_bytesize();
@ -12,12 +13,17 @@ bool translations_write(const uint8_t* data, uint32_t offset, uint32_t len) {
return false; return false;
} }
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_ASSETS);
ensure(flash_unlock_write(), "translations_write unlock"); ensure(flash_unlock_write(), "translations_write unlock");
// todo consider alignment // todo consider alignment
ensure(flash_area_write_data_padded(&TRANSLATIONS_AREA, offset, data, len, ensure(flash_area_write_data_padded(&TRANSLATIONS_AREA, offset, data, len,
0xFF, FLASH_ALIGN(len)), 0xFF, FLASH_ALIGN(len)),
"translations_write write"); "translations_write write");
ensure(flash_lock_write(), "translations_write lock"); ensure(flash_lock_write(), "translations_write lock");
mpu_restore(mpu_mode);
return true; return true;
} }
@ -30,7 +36,9 @@ const uint8_t* translations_read(uint32_t* len, uint32_t offset) {
} }
void translations_erase(void) { void translations_erase(void) {
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_ASSETS);
ensure(flash_area_erase(&TRANSLATIONS_AREA, NULL), "translations erase"); ensure(flash_area_erase(&TRANSLATIONS_AREA, NULL), "translations erase");
mpu_restore(mpu_mode);
} }
uint32_t translations_area_bytesize(void) { uint32_t translations_area_bytesize(void) {

View File

@ -2,6 +2,7 @@
#include "flash_otp.h" #include "flash_otp.h"
#include "model.h" #include "model.h"
#include "mpu.h"
#include "unit_variant.h" #include "unit_variant.h"
#include TREZOR_BOARD #include TREZOR_BOARD

View File

@ -77,20 +77,6 @@ const flash_area_t TRANSLATIONS_AREA = {
}, },
}; };
const flash_area_t WIPE_AREA = { const flash_area_t UNUSED_AREA = {
.num_subareas = 1, .num_subareas = 0,
.subarea[0] =
{
.first_sector = STORAGE_1_SECTOR_START,
.num_sectors = 488,
},
};
const flash_area_t ALL_WIPE_AREA = {
.num_subareas = 1,
.subarea[0] =
{
.first_sector = BOOTLOADER_SECTOR_START,
.num_sectors = 504,
},
}; };

View File

@ -74,21 +74,16 @@ const flash_area_t FIRMWARE_AREA = {
}, },
}; };
const flash_area_t WIPE_AREA = { const flash_area_t UNUSED_AREA = {
.num_subareas = 3, .num_subareas = 2,
.subarea[0] = .subarea[0] =
{ {
.first_sector = 4, .first_sector = 3,
.num_sectors = 1, .num_sectors = 1,
}, },
.subarea[1] = .subarea[1] =
{ {
.first_sector = 6, .first_sector = 15,
.num_sectors = 6, .num_sectors = 1,
},
.subarea[2] =
{
.first_sector = 16,
.num_sectors = 8,
}, },
}; };

View File

@ -65,35 +65,6 @@ const flash_area_t FIRMWARE_AREA = {
}, },
}; };
const flash_area_t WIPE_AREA = {
.num_subareas = 3,
.subarea[0] =
{
.first_sector = 4,
.num_sectors = 1,
},
.subarea[1] =
{
.first_sector = 6,
.num_sectors =
9, // sector 15 skipped due to bootloader MPU settings
},
.subarea[2] =
{
.first_sector = 16,
.num_sectors = 8,
},
};
const flash_area_t ALL_WIPE_AREA = {
.num_subareas = 1,
.subarea[0] =
{
.first_sector = 3,
.num_sectors = 21,
},
};
const flash_area_t SECRET_AREA = { const flash_area_t SECRET_AREA = {
.num_subareas = 1, .num_subareas = 1,
.subarea[0] = .subarea[0] =
@ -102,3 +73,17 @@ const flash_area_t SECRET_AREA = {
.num_sectors = 0, .num_sectors = 0,
}, },
}; };
const flash_area_t UNUSED_AREA = {
.num_subareas = 2,
.subarea[0] =
{
.first_sector = 3,
.num_sectors = 1,
},
.subarea[1] =
{
.first_sector = 15,
.num_sectors = 1,
},
};

View File

@ -77,20 +77,6 @@ const flash_area_t TRANSLATIONS_AREA = {
}, },
}; };
const flash_area_t WIPE_AREA = { const flash_area_t UNUSED_AREA = {
.num_subareas = 1, .num_subareas = 0,
.subarea[0] =
{
.first_sector = STORAGE_1_SECTOR_START,
.num_sectors = 232,
},
};
const flash_area_t ALL_WIPE_AREA = {
.num_subareas = 1,
.subarea[0] =
{
.first_sector = BOOTLOADER_SECTOR_START,
.num_sectors = 248,
},
}; };

View File

@ -77,20 +77,6 @@ const flash_area_t TRANSLATIONS_AREA = {
}, },
}; };
const flash_area_t WIPE_AREA = { const flash_area_t UNUSED_AREA = {
.num_subareas = 1, .num_subareas = 0,
.subarea[0] =
{
.first_sector = STORAGE_1_SECTOR_START,
.num_sectors = 232,
},
};
const flash_area_t ALL_WIPE_AREA = {
.num_subareas = 1,
.subarea[0] =
{
.first_sector = BOOTLOADER_SECTOR_START,
.num_sectors = 248,
},
}; };

View File

@ -20,7 +20,6 @@ extern const flash_area_t BHK_AREA;
extern const flash_area_t TRANSLATIONS_AREA; extern const flash_area_t TRANSLATIONS_AREA;
extern const flash_area_t BOOTLOADER_AREA; extern const flash_area_t BOOTLOADER_AREA;
extern const flash_area_t FIRMWARE_AREA; extern const flash_area_t FIRMWARE_AREA;
extern const flash_area_t WIPE_AREA; extern const flash_area_t UNUSED_AREA;
extern const flash_area_t ALL_WIPE_AREA;
#endif #endif

View File

@ -595,14 +595,19 @@ static void test_firmware_version(void) {
} }
static uint32_t read_bootloader_version(void) { static uint32_t read_bootloader_version(void) {
uint32_t version = 0;
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_BOOTUPDATE);
const image_header *header = read_image_header( const image_header *header = read_image_header(
(const uint8_t *)BOOTLOADER_START, BOOTLOADER_IMAGE_MAGIC, 0xffffffff); (const uint8_t *)BOOTLOADER_START, BOOTLOADER_IMAGE_MAGIC, 0xffffffff);
if (secfalse == header) { if (header != NULL) {
return 0; version = header->version;
} }
return header->version; mpu_restore(mpu_mode);
return version;
} }
static void test_bootloader_version(uint32_t version) { static void test_bootloader_version(uint32_t version) {
@ -809,15 +814,12 @@ int main(void) {
uint32_t bootloader_version = read_bootloader_version(); uint32_t bootloader_version = read_bootloader_version();
const boardloader_version_t *boardloader_version = read_boardloader_version(); const boardloader_version_t *boardloader_version = read_boardloader_version();
mpu_config_prodtest_initial();
#ifdef USE_OPTIGA #ifdef USE_OPTIGA
optiga_init(); optiga_init();
optiga_open_application(); optiga_open_application();
pair_optiga(); pair_optiga();
#endif #endif
mpu_config_prodtest();
fault_handlers_init(); fault_handlers_init();
display_clear(); display_clear();

View File

@ -17,15 +17,49 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef __MPU_H__ #ifndef TREZORHAL_MPU_H
#define __MPU_H__ #define TREZORHAL_MPU_H
void mpu_config_off(void); // The MPU driver can be set to on of the following modes.
void mpu_config_boardloader(void); //
void mpu_config_bootloader(void); // In each mode, the MPU is configured to allow access to specific
void mpu_config_firmware_initial(void); // memory regions.
void mpu_config_firmware(void); //
void mpu_config_prodtest_initial(void); // The `MPU_MODE_DEFAULT` mode is the most restrictive and serves as
void mpu_config_prodtest(void); // a base for other modes.
typedef enum {
MPU_MODE_DISABLED, // MPU is disabled
MPU_MODE_DEFAULT, // Default
MPU_MODE_BOARDCAPS, // + boardloader capabilities (privileged RO)
MPU_MODE_BOOTUPDATE, // + bootloader area (privileged RW)
MPU_MODE_OTP, // + OTP (privileged RW)
MPU_MODE_FSMC_REGS, // + FSMC control registers (privileged RW)
MPU_MODE_FLASHOB, // + Option bytes mapping (privileged RW)
MPU_MODE_SECRET, // + secret area (priviledeg RW)
MPU_MODE_STORAGE, // + both storage areas (privilehed RW)
MPU_MODE_ASSETS, // + assets (privileged RW)
MPU_MODE_UNUSED_FLASH, // + unused flash areas (privileged RW)
MPU_MODE_APP, // + unprivileged DMA2D (RW) & Assets (RO)
} mpu_mode_t;
#endif // Initializes the MPU and sets it to MPU_MODE_DISABLED.
//
// This function should be called before any other MPU function.
void mpu_init(void);
// Returns the current MPU mode.
//
// If the MPU is not initialized, returns MPU_MODE_DISABLED.
mpu_mode_t mpu_get_mode(void);
// Reconfigures the MPU to the given mode and returns the previous mode.
//
// If the MPU is not initialized, does nothing and returns MPU_MODE_DISABLED.
mpu_mode_t mpu_reconfig(mpu_mode_t mode);
// Restores the MPU to the given mode.
//
// Same as `mpu_reconfig()`, but with a more descriptive name.
void mpu_restore(mpu_mode_t mode);
#endif // TREZORHAL_MPU_H

View File

@ -17,10 +17,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "board_capabilities.h"
#include <string.h> #include <string.h>
#include "board_capabilities.h"
#include "common.h" #include "common.h"
#include "model.h" #include "model.h"
#include "mpu.h"
static uint32_t board_name = 0; static uint32_t board_name = 0;
@ -33,11 +35,14 @@ const boardloader_version_t *get_boardloader_version() {
} }
void parse_boardloader_capabilities() { void parse_boardloader_capabilities() {
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_BOARDCAPS);
const uint8_t *pos = (const uint8_t *)BOARD_CAPABILITIES_ADDR; const uint8_t *pos = (const uint8_t *)BOARD_CAPABILITIES_ADDR;
const uint8_t *end = const uint8_t *end =
(const uint8_t *)(BOARD_CAPABILITIES_ADDR + BOARD_CAPABILITIES_SIZE); (const uint8_t *)(BOARD_CAPABILITIES_ADDR + BOARD_CAPABILITIES_SIZE);
if (memcmp(pos, CAPABILITIES_HEADER, 4) != 0) { if (memcmp(pos, CAPABILITIES_HEADER, 4) != 0) {
mpu_restore(mpu_mode);
return; return;
} }
@ -70,6 +75,7 @@ void parse_boardloader_capabilities() {
memcpy(&boardloader_version, pos, length); memcpy(&boardloader_version, pos, length);
break; break;
case TAG_TERMINATOR: case TAG_TERMINATOR:
mpu_restore(mpu_mode);
return; return;
default: default:
break; break;
@ -77,4 +83,6 @@ void parse_boardloader_capabilities() {
pos += length; pos += length;
} }
mpu_restore(mpu_mode);
} }

View File

@ -91,7 +91,9 @@ reboot_with_args(boot_command_t command, const void* args, size_t args_size) {
#ifdef ENSURE_COMPATIBLE_SETTINGS #ifdef ENSURE_COMPATIBLE_SETTINGS
ensure_compatible_settings(); ensure_compatible_settings();
#endif #endif
mpu_config_bootloader();
mpu_reconfig(MPU_MODE_DISABLED);
jump_to_with_flag(BOOTLOADER_START + IMAGE_HEADER_SIZE, g_boot_command); jump_to_with_flag(BOOTLOADER_START + IMAGE_HEADER_SIZE, g_boot_command);
for (;;) for (;;)
; ;

View File

@ -22,6 +22,7 @@
#include "entropy.h" #include "entropy.h"
#include "flash_otp.h" #include "flash_otp.h"
#include "model.h" #include "model.h"
#include "mpu.h"
#include "rand.h" #include "rand.h"
#include "stm32f4xx_ll_utils.h" #include "stm32f4xx_ll_utils.h"
@ -29,6 +30,8 @@
static uint8_t g_hw_entropy[HW_ENTROPY_LEN]; static uint8_t g_hw_entropy[HW_ENTROPY_LEN];
void entropy_init(void) { void entropy_init(void) {
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP);
// collect entropy from UUID // collect entropy from UUID
uint32_t w = LL_GetUID_Word0(); uint32_t w = LL_GetUID_Word0();
memcpy(g_hw_entropy, &w, 4); memcpy(g_hw_entropy, &w, 4);
@ -37,6 +40,8 @@ void entropy_init(void) {
w = LL_GetUID_Word2(); w = LL_GetUID_Word2();
memcpy(g_hw_entropy + 8, &w, 4); memcpy(g_hw_entropy + 8, &w, 4);
mpu_restore(mpu_mode);
// set entropy in the OTP randomness block // set entropy in the OTP randomness block
if (secfalse == flash_otp_is_locked(FLASH_OTP_BLOCK_RANDOMNESS)) { if (secfalse == flash_otp_is_locked(FLASH_OTP_BLOCK_RANDOMNESS)) {
uint8_t entropy[FLASH_OTP_BLOCK_SIZE]; uint8_t entropy[FLASH_OTP_BLOCK_SIZE];

View File

@ -22,6 +22,7 @@
#include "flash_otp.h" #include "flash_otp.h"
#include "common.h" #include "common.h"
#include "flash.h" #include "flash.h"
#include "mpu.h"
#define FLASH_OTP_LOCK_BASE 0x1FFF7A00U #define FLASH_OTP_LOCK_BASE 0x1FFF7A00U
@ -35,10 +36,16 @@ secbool flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data,
offset + datalen > FLASH_OTP_BLOCK_SIZE) { offset + datalen > FLASH_OTP_BLOCK_SIZE) {
return secfalse; return secfalse;
} }
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP);
for (uint8_t i = 0; i < datalen; i++) { for (uint8_t i = 0; i < datalen; i++) {
data[i] = *(__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE + data[i] = *(__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE +
offset + i); offset + i);
} }
mpu_restore(mpu_mode);
return sectrue; return sectrue;
} }
@ -48,6 +55,9 @@ secbool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data,
offset + datalen > FLASH_OTP_BLOCK_SIZE) { offset + datalen > FLASH_OTP_BLOCK_SIZE) {
return secfalse; return secfalse;
} }
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP);
ensure(flash_unlock_write(), NULL); ensure(flash_unlock_write(), NULL);
for (uint8_t i = 0; i < datalen; i++) { for (uint8_t i = 0; i < datalen; i++) {
uint32_t address = uint32_t address =
@ -57,6 +67,9 @@ secbool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data,
NULL); NULL);
} }
ensure(flash_lock_write(), NULL); ensure(flash_lock_write(), NULL);
mpu_restore(mpu_mode);
return sectrue; return sectrue;
} }
@ -64,13 +77,28 @@ secbool flash_otp_lock(uint8_t block) {
if (block >= FLASH_OTP_NUM_BLOCKS) { if (block >= FLASH_OTP_NUM_BLOCKS) {
return secfalse; return secfalse;
} }
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP);
ensure(flash_unlock_write(), NULL); ensure(flash_unlock_write(), NULL);
HAL_StatusTypeDef ret = HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, HAL_StatusTypeDef ret = HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE,
FLASH_OTP_LOCK_BASE + block, 0x00); FLASH_OTP_LOCK_BASE + block, 0x00);
ensure(flash_lock_write(), NULL); ensure(flash_lock_write(), NULL);
mpu_restore(mpu_mode);
return sectrue * (ret == HAL_OK); return sectrue * (ret == HAL_OK);
} }
secbool flash_otp_is_locked(uint8_t block) { secbool flash_otp_is_locked(uint8_t block) {
return sectrue * (0x00 == *(__IO uint8_t *)(FLASH_OTP_LOCK_BASE + 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;
} }

View File

@ -20,6 +20,9 @@
#include STM32_HAL_H #include STM32_HAL_H
#include "lowlevel.h" #include "lowlevel.h"
#include <mpu.h>
#include "flash_otp.h" #include "flash_otp.h"
#pragma GCC optimize( \ #pragma GCC optimize( \
@ -80,19 +83,27 @@ secbool flash_check_option_bytes(void) {
if (FLASH->OPTCR1 != FLASH_OPTCR1_nWRP) { if (FLASH->OPTCR1 != FLASH_OPTCR1_nWRP) {
return secfalse; return secfalse;
} }
mpu_mode_t mode = mpu_reconfig(MPU_MODE_FLASHOB);
// check values stored in flash memory // check values stored in flash memory
if ((OPTION_BYTES_RDP_USER & ~3) != if ((OPTION_BYTES_RDP_USER & ~3) !=
OPTION_BYTES_RDP_USER_VALUE) { // bits 0 and 1 are unused OPTION_BYTES_RDP_USER_VALUE) { // bits 0 and 1 are unused
mpu_reconfig(mode);
return secfalse; return secfalse;
} }
if ((OPTION_BYTES_BANK1_WRP & 0xCFFFU) != if ((OPTION_BYTES_BANK1_WRP & 0xCFFFU) !=
OPTION_BYTES_BANK1_WRP_VALUE) { // bits 12 and 13 are unused OPTION_BYTES_BANK1_WRP_VALUE) { // bits 12 and 13 are unused
mpu_reconfig(mode);
return secfalse; return secfalse;
} }
if ((OPTION_BYTES_BANK2_WRP & 0xFFFU) != if ((OPTION_BYTES_BANK2_WRP & 0xFFFU) !=
OPTION_BYTES_BANK2_WRP_VALUE) { // bits 12, 13, 14, and 15 are unused OPTION_BYTES_BANK2_WRP_VALUE) { // bits 12, 13, 14, and 15 are unused
mpu_reconfig(mode);
return secfalse; return secfalse;
} }
mpu_reconfig(mode);
return sectrue; return sectrue;
} }

View File

@ -20,6 +20,7 @@
#include "monoctr.h" #include "monoctr.h"
#include "flash_otp.h" #include "flash_otp.h"
#include "model.h" #include "model.h"
#include "mpu.h"
#include "string.h" #include "string.h"
#if !PRODUCTION #if !PRODUCTION

View File

@ -19,292 +19,338 @@
#include STM32_HAL_H #include STM32_HAL_H
#include TREZOR_BOARD #include TREZOR_BOARD
#include <stdbool.h>
#include <stdint.h>
#include "irq.h"
#include "model.h"
#include "mpu.h"
#include "stm32f4xx_ll_cortex.h" #include "stm32f4xx_ll_cortex.h"
// http://infocenter.arm.com/help/topic/com.arm.doc.dui0552a/BABDJJGF.html // http://infocenter.arm.com/help/topic/com.arm.doc.dui0552a/BABDJJGF.html
#define MPU_RASR_ATTR_FLASH (MPU_RASR_C_Msk) #define MPU_RASR_ATTR_FLASH_CODE (MPU_RASR_C_Msk)
#define MPU_RASR_ATTR_SRAM (MPU_RASR_C_Msk | MPU_RASR_S_Msk) #define MPU_RASR_ATTR_FLASH_DATA (MPU_RASR_C_Msk | MPU_RASR_XN_Msk)
#define MPU_RASR_ATTR_PERIPH (MPU_RASR_B_Msk | MPU_RASR_S_Msk) #define MPU_RASR_ATTR_SRAM (MPU_RASR_C_Msk | MPU_RASR_S_Msk | MPU_RASR_XN_Msk)
#define MPU_RASR_ATTR_PERIPH (MPU_RASR_B_Msk | MPU_RASR_S_Msk | MPU_RASR_XN_Msk)
#define MPU_SUBREGION_DISABLE(X) ((X) << MPU_RASR_SRD_Pos) #define SET_REGION(region, start, size, mask, attr, access) \
do { \
uint32_t _enable = MPU_RASR_ENABLE_Msk; \
uint32_t _size = LL_MPU_REGION_##size; \
uint32_t _mask = (mask) << MPU_RASR_SRD_Pos; \
uint32_t _attr = MPU_RASR_ATTR_##attr; \
uint32_t _access = LL_MPU_REGION_##access; \
MPU->RNR = region; \
MPU->RBAR = (start) & ~0x1F; \
MPU->RASR = _enable | _size | _mask | _attr | _access; \
} while (0)
void mpu_config_off(void) { #define DIS_REGION(region) \
// Disable MPU do { \
HAL_MPU_Disable(); MPU->RNR = region; \
} MPU->RBAR = 0; \
MPU->RASR = 0; \
} while (0)
void mpu_config_boardloader(void) { typedef struct {
// nothing to be done // Set if the driver is initialized
} bool initialized;
// Current mode
mpu_mode_t mode;
void mpu_config_bootloader(void) { } mpu_driver_t;
// Disable MPU
HAL_MPU_Disable();
// Note: later entries overwrite previous ones mpu_driver_t g_mpu_driver = {
.initialized = false,
.mode = MPU_MODE_DISABLED,
};
// Everything (0x00000000 - 0xFFFFFFFF, 4 GiB, read-write) static void mpu_init_fixed_regions(void) {
MPU->RNR = MPU_REGION_NUMBER0; // Regions #0 to #4 are fixed for all targets
MPU->RBAR = 0;
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH |
LL_MPU_REGION_SIZE_4GB | LL_MPU_REGION_FULL_ACCESS;
// Flash (0x0800C000 - 0x0800FFFF, 16 KiB, no access) #ifdef BOARDLOADER
MPU->RNR = MPU_REGION_NUMBER1; // clang-format off
MPU->RBAR = FLASH_BASE + 0xC000; // Code in the Flash Bank #1 (Unprivileged, Read-Only, Executable)
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | // Subregion: 48KB = 64KB except 2/8 at end
LL_MPU_REGION_SIZE_16KB | LL_MPU_REGION_NO_ACCESS; SET_REGION( 0, BOARDLOADER_START, SIZE_64KB, 0xC0, FLASH_CODE, PRIV_RO_URO );
// Rest of the code in the Flash Bank #1 (Unprivileged, Read-Only)
// Flash (0x0810C000 - 0x0810FFFF, 16 KiB, no access) // Subregion: 896KB = 1024KB except 1/8 at start
MPU->RNR = MPU_REGION_NUMBER2; SET_REGION( 1, FLASH_BASE, SIZE_1MB, 0x01, FLASH_DATA, FULL_ACCESS );
MPU->RBAR = FLASH_BASE + 0x10C000; // Rest of the code in the Flash Bank #2 (Unprivileged, Read-Only)
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | // Subregion: 896KB = 1024KB except 1/8 at start
LL_MPU_REGION_SIZE_16KB | LL_MPU_REGION_NO_ACCESS; SET_REGION( 2, FLASH_BASE + 0x100000, SIZE_1MB, 0x01, FLASH_DATA, FULL_ACCESS );
// All CCMRAM (Unprivileged, Read-Write, Non-Executable)
// SRAM (0x20000000 - 0x2002FFFF, 192 KiB = 256 KiB except 2/8 at end, SET_REGION( 3, CCMDATARAM_BASE, SIZE_64KB, 0x00, SRAM, FULL_ACCESS );
// read-write, execute never) // All SRAM (Unprivileged, Read-Write, Non-Executable)
MPU->RNR = MPU_REGION_NUMBER3; // Subregion: 192KB = 256KB except 2/8 at end
MPU->RBAR = SRAM_BASE; SET_REGION( 4, SRAM_BASE, SIZE_256KB, 0xC0, SRAM, FULL_ACCESS );
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_SRAM | // clang-format on
LL_MPU_REGION_SIZE_256KB | LL_MPU_REGION_FULL_ACCESS | #endif
MPU_RASR_XN_Msk | MPU_SUBREGION_DISABLE(0xC0); #ifdef BOOTLOADER
// clang-format off
#ifdef USE_SDRAM // Bootloader code in the Flash Bank #1 (Unprivileged, Read-Only, Executable)
// Peripherals (0x40000000 - 0x5FFFFFFF, read-write, execute never) // Subregion: 128KB = 1024KB except 2/8 at start
// SDRAM (0xC0000000 - 0xDFFFFFFF, read-write, execute never) SET_REGION( 0, BOOTLOADER_START, SIZE_128KB, 0x00, FLASH_CODE, PRIV_RO_URO );
MPU->RNR = MPU_REGION_NUMBER4; // Kernel/coreapp code in the Flash Bank #1 (Unprivileged, Read-Only)
MPU->RBAR = 0; // Subregion: 768KB = 1024KB except 2/8 at start
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_PERIPH | SET_REGION( 1, FLASH_BASE, SIZE_1MB, 0x03, FLASH_DATA, FULL_ACCESS );
LL_MPU_REGION_SIZE_4GB | LL_MPU_REGION_FULL_ACCESS | // Kernel/coreapp code in the Flash Bank #2 (Unprivileged, Read-Only)
MPU_RASR_XN_Msk | MPU_SUBREGION_DISABLE(0xBB); // Subregion: 896KB = 1024KB except 1/8 at start
#else SET_REGION( 2, FLASH_BASE + 0x100000, SIZE_1MB, 0x01, FLASH_DATA, FULL_ACCESS );
// Peripherals (0x40000000 - 0x5FFFFFFF, read-write, execute never) // All CCMRAM (Unprivileged, Read-Write, Non-Executable)
// External RAM (0x60000000 - 0x7FFFFFFF, read-write, execute never) SET_REGION( 3, CCMDATARAM_BASE, SIZE_64KB, 0x00, SRAM, FULL_ACCESS );
MPU->RNR = MPU_REGION_NUMBER4; // All SRAM (Unprivileged, Read-Write, Non-Executable)
MPU->RBAR = PERIPH_BASE; // Subregion: 192KB = 256KB except 2/8 at end
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_PERIPH | SET_REGION( 4, SRAM_BASE, SIZE_256KB, 0xC0, SRAM, FULL_ACCESS );
LL_MPU_REGION_SIZE_1GB | LL_MPU_REGION_FULL_ACCESS | // clang-format on
MPU_RASR_XN_Msk; #endif
#ifdef KERNEL
// clang-format off
// Code in the Flash Bank #1 (Unprivileged, Read-Only, Executable)
// Subregion: 768KB = 1024KB except 2/8 at start
SET_REGION( 0, FLASH_BASE, SIZE_1MB, 0x03, FLASH_CODE, PRIV_RO_URO );
// Code in the Flash Bank #2 (Unprivileged, Read-Only, Executable)
// Subregion: 896KB = 1024KB except 1/8 at start
SET_REGION( 1, FLASH_BASE + 0x100000, SIZE_1MB, 0x01, FLASH_CODE, PRIV_RO_URO );
// All CCMRAM (Unprivileged, Read-Write, Non-Executable)
SET_REGION( 2, CCMDATARAM_BASE, SIZE_64KB, 0x00, SRAM, FULL_ACCESS );
// All SRAM (Unprivileged, Read-Write, Non-Executable)
// Subregion: 192KB = 256KB except 2/8 at end
SET_REGION( 3, SRAM_BASE, SIZE_256KB, 0xC0, SRAM, FULL_ACCESS );
// Kernel RAM (Privileged, Read-Write, Non-Executable)
// TODO: !@#
// SET_REGION( 4, ..., SIZE_xxx, 0xXX, ATTR_SRAM, PRIV_RW );
DIS_REGION( 4 );
// clang-format on
#endif
#ifdef FIRMWARE
// clang-format off
// Code in the Flash Bank #1 (Unprivileged, Read-Only, Executable)
// Subregion: 768KB = 1024KB except 2/8 at start
SET_REGION( 0, FLASH_BASE, SIZE_1MB, 0x03, FLASH_CODE, PRIV_RO_URO );
// Code in the Flash Bank #2 (Unprivileged, Read-Only, Executable)
// Subregion: 896KB = 1024KB except 1/8 at start
SET_REGION( 1, FLASH_BASE + 0x100000, SIZE_1MB, 0x01, FLASH_CODE, PRIV_RO_URO );
// All CCMRAM (Unprivileged, Read-Write, Non-Executable)
SET_REGION( 2, CCMDATARAM_BASE, SIZE_64KB, 0x00, SRAM, FULL_ACCESS );
// All SRAM (Unprivileged, Read-Write, Non-Executable)
// Subregion: 192KB = 256KB except 2/8 at end
SET_REGION( 3, SRAM_BASE, SIZE_256KB, 0xC0, SRAM, FULL_ACCESS );
DIS_REGION( 4 );
// clang-format on
#endif
#ifdef TREZOR_PRODTEST
// clang-format off
// Code in the Flash Bank #1 (Unprivileged, Read-Only, Executable)
// Subregion: 768KB = 1024KB except 2/8 at start
SET_REGION( 0, FLASH_BASE, SIZE_1MB, 0x03, FLASH_CODE, PRIV_RO_URO );
// Code in the Flash Bank #2 (Unprivileged, Read-Only, Executable)
// Subregion: 896KB = 1024KB except 1/8 at start
SET_REGION( 1, FLASH_BASE + 0x100000, SIZE_1MB, 0x01, FLASH_CODE, PRIV_RO_URO );
// All CCMRAM (Unprivileged, Read-Write, Non-Executable)
SET_REGION( 2, CCMDATARAM_BASE, SIZE_64KB, 0x00, SRAM, FULL_ACCESS );
// All SRAM (Unprivileged, Read-Write, Non-Executable)
// Subregion: 192KB = 256KB except 2/8 at end
SET_REGION( 3, SRAM_BASE, SIZE_256KB, 0xC0, SRAM, FULL_ACCESS );
// Firmware header (Unprivileged, Read-Write, Non-Executable)
// (used in production test to invalidate the firmware)
SET_REGION( 4, FIRMWARE_START, SIZE_1KB, 0x00, FLASH_DATA, PRIV_RW_URO );
// clang-format on
#endif #endif
#if defined STM32F427xx || defined STM32F429xx // Regions #5 to #7 are banked
// CCMRAM (0x10000000 - 0x1000FFFF, read-write, execute never) DIS_REGION(5);
MPU->RNR = MPU_REGION_NUMBER5; DIS_REGION(6);
MPU->RBAR = CCMDATARAM_BASE; DIS_REGION(7);
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_SRAM |
LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_FULL_ACCESS |
MPU_RASR_XN_Msk;
#elif STM32F405xx
// no CCMRAM
#else
#error Unsupported MCU
#endif
// Enable MPU
HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI);
} }
void mpu_config_firmware_initial(void) {} void mpu_init(void) {
mpu_driver_t* drv = &g_mpu_driver;
if (drv->initialized) {
return;
}
irq_key_t irq_key = irq_lock();
void mpu_config_firmware(void) {
// Disable MPU
HAL_MPU_Disable(); HAL_MPU_Disable();
// Note: later entries overwrite previous ones mpu_init_fixed_regions();
/* drv->mode = MPU_MODE_DISABLED;
// Boardloader (0x08000000 - 0x0800FFFF, 64 KiB, read-only, execute never) drv->initialized = true;
MPU->RBAR = FLASH_BASE | MPU_REGION_NUMBER0;
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH |
LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_PRIV_RO_URO | MPU_RASR_XN_Msk;
*/
// Bootloader (0x08020000 - 0x0803FFFF, 128 KiB, read-only) irq_unlock(irq_key);
MPU->RNR = MPU_REGION_NUMBER0; }
MPU->RBAR = FLASH_BASE + 0x20000;
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH |
LL_MPU_REGION_SIZE_128KB | LL_MPU_REGION_PRIV_RO_URO;
// Storage#1 (0x08010000 - 0x0801FFFF, 64 KiB, read-write, execute never) mpu_mode_t mpu_get_mode(void) {
MPU->RNR = MPU_REGION_NUMBER1; mpu_driver_t* drv = &g_mpu_driver;
MPU->RBAR = FLASH_BASE + 0x10000;
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | if (!drv->initialized) {
LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_FULL_ACCESS | return MPU_MODE_DISABLED;
MPU_RASR_XN_Msk; }
return drv->mode;
}
// STM32F4xx memory map
//
// 0x08000000 2MB FLASH
// 0x10000000 64KB CCMRAM
// 0x1FFF7800 528B OTP
// 0x20000000 192KB SRAM
// 0x40000000 512MB PERIPH
// STM32F4xx flash layout
//
// 0x08000000 4x 16KB (BANK #1)
// 0x08010000 1x 64KB (BANK #1)
// 0x08020000 7x 128KB (BANK #1)
// 0x08100000 4x 16KB (BANK #2)
// 0x08110000 1x 64KB (BANK #3)
// 0x08120000 7x 128KB (BANK #4)
mpu_mode_t mpu_reconfig(mpu_mode_t mode) {
mpu_driver_t* drv = &g_mpu_driver;
if (!drv->initialized) {
// Solves the issue when some IRQ handler tries to reconfigure
// MPU before it is initialized
return MPU_MODE_DISABLED;
}
irq_key_t irq_key = irq_lock();
HAL_MPU_Disable();
// Region #5 and #6 are banked
// clang-format off
switch (mode) {
#if !defined(BOARDLOADER)
case MPU_MODE_BOARDCAPS:
DIS_REGION( 5 );
// Boardloader (Privileged, Read-Only, Non-Executable)
// Subregion: 48KB = 64KB except 2/8 at end
SET_REGION( 6, FLASH_BASE, SIZE_64KB, 0xC0, FLASH_DATA, PRIV_RO );
break;
#endif
#if !defined(BOARDLOADER) && !defined(BOOTLOADER)
case MPU_MODE_BOOTUPDATE:
DIS_REGION( 5 );
// Bootloader (Privileged, Read-Write, Non-Executable)
SET_REGION( 6, FLASH_BASE + 0x20000, SIZE_128KB, 0x00, FLASH_DATA, PRIV_RW );
break;
#endif
case MPU_MODE_OTP:
DIS_REGION( 5 );
// OTP (Privileged, Read-Write, Non-Executable)
SET_REGION( 6, FLASH_OTP_BASE, SIZE_1KB, 0x00, FLASH_DATA, FULL_ACCESS );
break;
case MPU_MODE_FSMC_REGS:
DIS_REGION( 5 );
// FSMC Control Registers (Privileged, Read-Write, Non-Executable)
// 0xA0000000 = FMSC_R_BASE (not defined in used headers)
SET_REGION( 6, 0xA0000000, SIZE_4KB, 0x00, FLASH_DATA, FULL_ACCESS );
break;
case MPU_MODE_FLASHOB:
SET_REGION( 5, 0x1FFFC000, SIZE_1KB, 0x00, FLASH_DATA, PRIV_RO );
SET_REGION( 6, 0x1FFEC000, SIZE_1KB, 0x00, FLASH_DATA, PRIV_RO );
break;
case MPU_MODE_UNUSED_FLASH:
// Unused Flash Area #1 (Privileged, Read-Write, Non-Executable)
SET_REGION( 5, FLASH_BASE + 0x00C000, SIZE_16KB, 0x00, FLASH_DATA, PRIV_RW );
// Unused Flash Area #2 (Privileged, Read-Write, Non-Executable)
SET_REGION( 6, FLASH_BASE + 0x10C000, SIZE_16KB, 0x00, FLASH_DATA, PRIV_RW );
break;
#ifdef USE_OPTIGA #ifdef USE_OPTIGA
// Translations + Storage#2 - secret (0x08104000 - 0x0811FFFF, 112 KiB, // with optiga, we use the secret sector, and assets area is smaller
// read-write, execute never) case MPU_MODE_SECRET:
MPU->RNR = MPU_REGION_NUMBER2; DIS_REGION( 5 );
MPU->RBAR = FLASH_BASE + 0x100000; // Secret sector in Bank #2 (Privileged, Read-Write, Non-Executable)
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | SET_REGION( 6, FLASH_BASE + 0x100000, SIZE_16KB, 0x00, FLASH_DATA, PRIV_RW );
LL_MPU_REGION_SIZE_128KB | LL_MPU_REGION_FULL_ACCESS | break;
MPU_RASR_XN_Msk | MPU_SUBREGION_DISABLE(0x01);
case MPU_MODE_ASSETS:
DIS_REGION( 5 );
// Assets (Privileged, Read-Write, Non-Executable)
SET_REGION( 6, FLASH_BASE + 0x108000, SIZE_32KB, 0x00, FLASH_DATA, PRIV_RW );
break;
case MPU_MODE_APP:
// Unused (maybe privileged kernel code in the future)
DIS_REGION( 5 );
// Assets (Unprivileged, Read-Only, Non-Executable)
SET_REGION( 6, FLASH_BASE + 0x108000, SIZE_32KB, 0x00, FLASH_DATA, PRIV_RO_URO );
break;
#else #else
// Translations + Storage#2 (0x08100000 - 0x0811FFFF, 128 KiB, read-write, // without optiga, we use additional sector for assets area
// execute never) case MPU_MODE_ASSETS:
MPU->RNR = MPU_REGION_NUMBER2; DIS_REGION( 5 );
MPU->RBAR = FLASH_BASE + 0x100000; // Assets (Privileged, Read-Write, Non-Executable)
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | // Subregion: 48KB = 64KB except 2/8 at end
LL_MPU_REGION_SIZE_128KB | LL_MPU_REGION_FULL_ACCESS | SET_REGION( 6, FLASH_BASE + 0x100000, SIZE_64KB, 0xC0, FLASH_DATA, PRIV_RW );
MPU_RASR_XN_Msk; break;
case MPU_MODE_APP:
// Unused (maybe privileged kernel code in the future)
DIS_REGION( 5 );
// Assets (Unprivileged, Read-Only, Non-Executable)
// Subregion: 48KB = 64KB except 2/8 at end
SET_REGION( 6, FLASH_BASE + 0x100000, SIZE_64KB, 0xC0, FLASH_DATA, PRIV_RO_URO );
break;
#endif #endif
// Firmware (0x08040000 - 0x080FFFFF, 6 * 128 KiB = 1024 KiB except 2/8 at case MPU_MODE_STORAGE:
// start = 768 KiB, read-only) // Storage in the Flash Bank #1 (Privileged, Read-Write, Non-Executable)
MPU->RNR = MPU_REGION_NUMBER3; SET_REGION( 5, FLASH_BASE + 0x10000, SIZE_64KB, 0x00, FLASH_DATA, PRIV_RW );
MPU->RBAR = FLASH_BASE; // Storage in the Flash Bank #2 (Privileged, Read-Write, Non-Executable)
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | SET_REGION( 6, FLASH_BASE + 0x110000, SIZE_64KB, 0x00, FLASH_DATA, PRIV_RW );
LL_MPU_REGION_SIZE_1MB | LL_MPU_REGION_PRIV_RO_URO | break;
MPU_SUBREGION_DISABLE(0x03);
// Firmware extra (0x08120000 - 0x081FFFFF, 7 * 128 KiB = 1024 KiB except 1/8 default:
// at start = 896 KiB, read-only) DIS_REGION( 5 );
MPU->RNR = MPU_REGION_NUMBER4; DIS_REGION( 6 );
MPU->RBAR = FLASH_BASE + 0x100000; break;
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | }
LL_MPU_REGION_SIZE_1MB | LL_MPU_REGION_PRIV_RO_URO | // clang-format on
MPU_SUBREGION_DISABLE(0x01);
// SRAM (0x20000000 - 0x2002FFFF, 192 KiB = 256 KiB except 2/8 at end, // Region #7 is banked
// read-write, execute never)
MPU->RNR = MPU_REGION_NUMBER5;
MPU->RBAR = SRAM_BASE;
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_SRAM |
LL_MPU_REGION_SIZE_256KB | LL_MPU_REGION_FULL_ACCESS |
MPU_RASR_XN_Msk | MPU_SUBREGION_DISABLE(0xC0);
#ifdef USE_SDRAM // clang-format off
// Peripherals (0x40000000 - 0x5FFFFFFF, read-write, execute never) switch (mode) {
// SDRAM (0xC0000000 - 0xDFFFFFFF, read-write, execute never) case MPU_MODE_APP:
MPU->RNR = MPU_REGION_NUMBER6; // Dma2D (Unprivileged, Read-Write, Non-Executable)
MPU->RBAR = 0; // 3KB = 4KB except 1/4 at end
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_PERIPH | SET_REGION( 7, 0x4002B000, SIZE_4KB, 0xC0, PERIPH, FULL_ACCESS );
LL_MPU_REGION_SIZE_4GB | LL_MPU_REGION_FULL_ACCESS | break;
MPU_RASR_XN_Msk | MPU_SUBREGION_DISABLE(0xBB); default:
#else // All Peripherals (Privileged, Read-Write, Non-Executable)
// Peripherals (0x40000000 - 0x5FFFFFFF, read-write, execute never) SET_REGION( 7, PERIPH_BASE, SIZE_1GB, 0x00, PERIPH, PRIV_RW );
// External RAM (0x60000000 - 0x7FFFFFFF, read-write, execute never) break;
MPU->RNR = MPU_REGION_NUMBER6; }
MPU->RBAR = PERIPH_BASE; // clang-format on
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_PERIPH |
LL_MPU_REGION_SIZE_1GB | LL_MPU_REGION_FULL_ACCESS |
MPU_RASR_XN_Msk;
#endif
#if defined STM32F427xx || defined STM32F429xx if (mode != MPU_MODE_DISABLED) {
// CCMRAM (0x10000000 - 0x1000FFFF, read-write, execute never) HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI);
MPU->RNR = MPU_REGION_NUMBER7; }
MPU->RBAR = CCMDATARAM_BASE;
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_SRAM |
LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_FULL_ACCESS |
MPU_RASR_XN_Msk;
#elif STM32F405xx
// no CCMRAM
#else
#error Unsupported MCU
#endif
// Enable MPU mpu_mode_t prev_mode = drv->mode;
HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI); drv->mode = mode;
__asm__ volatile("dsb"); irq_unlock(irq_key);
__asm__ volatile("isb");
return prev_mode;
} }
void mpu_config_prodtest_initial(void) {} void mpu_restore(mpu_mode_t mode) { mpu_reconfig(mode); }
void mpu_config_prodtest(void) {
// Disable MPU
HAL_MPU_Disable();
// Note: later entries overwrite previous ones
// // Boardloader (0x08000000 - 0x0800BFFF, 48 KiB, read-only, execute never)
// MPU->RNR = MPU_REGION_NUMBER0;
// MPU->RBAR = FLASH_BASE;
// MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH |
// LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_PRIV_RO_URO |
// MPU_RASR_XN_Msk | MPU_SUBREGION_DISABLE(0xC0);
// Secret area (0x08100000 - 0x08103FFF, 16 KiB, read-write, execute never)
// MPU->RNR = MPU_REGION_NUMBER0;
// MPU->RBAR = FLASH_BASE + 0x100000;
// MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH |
// LL_MPU_REGION_SIZE_16KB | LL_MPU_REGION_FULL_ACCESS |
// MPU_RASR_XN_Msk;
// Bootloader (0x08020000 - 0x0803FFFF, 64 KiB, read-only)
MPU->RNR = MPU_REGION_NUMBER1;
MPU->RBAR = FLASH_BASE + 0x20000;
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH |
LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_PRIV_RO_URO;
// Firmware (0x08040000 - 0x080FFFFF, 6 * 128 KiB = 1024 KiB except 2/8 at
// start = 768 KiB, read-only)
MPU->RNR = MPU_REGION_NUMBER2;
MPU->RBAR = FLASH_BASE;
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH |
LL_MPU_REGION_SIZE_1MB | LL_MPU_REGION_FULL_ACCESS |
MPU_SUBREGION_DISABLE(0x03);
// Firmware extra (0x08120000 - 0x081FFFFF, 7 * 128 KiB = 1024 KiB except 1/8
// at start = 896 KiB, read-only)
MPU->RNR = MPU_REGION_NUMBER3;
MPU->RBAR = FLASH_BASE + 0x100000;
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH |
LL_MPU_REGION_SIZE_1MB | LL_MPU_REGION_FULL_ACCESS |
MPU_SUBREGION_DISABLE(0x01);
// SRAM (0x20000000 - 0x2002FFFF, 192 KiB = 256 KiB except 2/8 at end,
// read-write, execute never)
MPU->RNR = MPU_REGION_NUMBER4;
MPU->RBAR = SRAM_BASE;
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_SRAM |
LL_MPU_REGION_SIZE_256KB | LL_MPU_REGION_FULL_ACCESS |
MPU_RASR_XN_Msk | MPU_SUBREGION_DISABLE(0xC0);
#ifdef USE_SDRAM
// Peripherals (0x40000000 - 0x5FFFFFFF, read-write, execute never)
// SDRAM (0xC0000000 - 0xDFFFFFFF, read-write, execute never)
MPU->RNR = MPU_REGION_NUMBER5;
MPU->RBAR = 0;
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_PERIPH |
LL_MPU_REGION_SIZE_4GB | LL_MPU_REGION_FULL_ACCESS |
MPU_RASR_XN_Msk | MPU_SUBREGION_DISABLE(0xBB);
#else
// Peripherals (0x40000000 - 0x5FFFFFFF, read-write, execute never)
// External RAM (0x60000000 - 0x7FFFFFFF, read-write, execute never)
MPU->RNR = MPU_REGION_NUMBER5;
MPU->RBAR = PERIPH_BASE;
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_PERIPH |
LL_MPU_REGION_SIZE_1GB | LL_MPU_REGION_FULL_ACCESS |
MPU_RASR_XN_Msk;
#endif
#if defined STM32F427xx || defined STM32F429xx
// CCMRAM (0x10000000 - 0x1000FFFF, read-write, execute never)
MPU->RNR = MPU_REGION_NUMBER6;
MPU->RBAR = CCMDATARAM_BASE;
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_SRAM |
LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_FULL_ACCESS |
MPU_RASR_XN_Msk;
#elif STM32F405xx
// no CCMRAM
#else
#error Unsupported MCU
#endif
// OTP (0x1FFF7800 - 0x1FFF7C00, read-write, execute never)
MPU->RNR = MPU_REGION_NUMBER7;
MPU->RBAR = FLASH_OTP_BASE;
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH |
LL_MPU_REGION_SIZE_1KB | LL_MPU_REGION_FULL_ACCESS |
MPU_RASR_XN_Msk;
// Enable MPU
HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI);
__asm__ volatile("dsb");
__asm__ volatile("isb");
}

View File

@ -4,6 +4,7 @@
#include "display_draw.h" #include "display_draw.h"
#include "flash.h" #include "flash.h"
#include "model.h" #include "model.h"
#include "mpu.h"
#ifdef FANCY_FATAL_ERROR #ifdef FANCY_FATAL_ERROR
#include "rust_ui.h" #include "rust_ui.h"
@ -20,10 +21,15 @@ secbool secret_verify_header(void) {
return secfalse; return secfalse;
} }
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET);
bootloader_locked = bootloader_locked =
memcmp(addr, SECRET_HEADER_MAGIC, sizeof(SECRET_HEADER_MAGIC)) == 0 memcmp(addr, SECRET_HEADER_MAGIC, sizeof(SECRET_HEADER_MAGIC)) == 0
? sectrue ? sectrue
: secfalse; : secfalse;
mpu_restore(mpu_mode);
bootloader_locked_set = sectrue; bootloader_locked_set = sectrue;
return bootloader_locked; return bootloader_locked;
} }
@ -44,12 +50,14 @@ void secret_write_header(void) {
} }
void secret_write(const uint8_t* data, uint32_t offset, uint32_t len) { void secret_write(const uint8_t* data, uint32_t offset, uint32_t len) {
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET);
ensure(flash_unlock_write(), "secret write"); ensure(flash_unlock_write(), "secret write");
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
ensure(flash_area_write_byte(&SECRET_AREA, offset + i, data[i]), ensure(flash_area_write_byte(&SECRET_AREA, offset + i, data[i]),
"secret write"); "secret write");
} }
ensure(flash_lock_write(), "secret write"); ensure(flash_lock_write(), "secret write");
mpu_restore(mpu_mode);
} }
secbool secret_read(uint8_t* data, uint32_t offset, uint32_t len) { secbool secret_read(uint8_t* data, uint32_t offset, uint32_t len) {
@ -63,28 +71,40 @@ secbool secret_read(uint8_t* data, uint32_t offset, uint32_t len) {
return secfalse; return secfalse;
} }
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET);
memcpy(data, addr, len); memcpy(data, addr, len);
mpu_restore(mpu_mode);
return sectrue; return sectrue;
} }
secbool secret_wiped(void) { secbool secret_wiped(void) {
uint32_t size = flash_area_get_size(&SECRET_AREA); uint32_t size = flash_area_get_size(&SECRET_AREA);
secbool wiped = sectrue;
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET);
for (int i = 0; i < size; i += 4) { for (int i = 0; i < size; i += 4) {
uint32_t* addr = (uint32_t*)flash_area_get_address(&SECRET_AREA, i, 4); uint32_t* addr = (uint32_t*)flash_area_get_address(&SECRET_AREA, i, 4);
if (addr == NULL) { if (addr == NULL) {
return secfalse; wiped = secfalse;
break;
} }
if (*addr != 0xFFFFFFFF) { if (*addr != 0xFFFFFFFF) {
return secfalse; wiped = secfalse;
break;
} }
} }
return sectrue;
mpu_restore(mpu_mode);
return wiped;
} }
void secret_erase(void) { void secret_erase(void) {
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET);
ensure(flash_area_erase(&SECRET_AREA, NULL), "secret erase"); ensure(flash_area_erase(&SECRET_AREA, NULL), "secret erase");
mpu_restore(mpu_mode);
} }
secbool secret_optiga_set(const uint8_t secret[SECRET_OPTIGA_KEY_LEN]) { secbool secret_optiga_set(const uint8_t secret[SECRET_OPTIGA_KEY_LEN]) {

View File

@ -22,6 +22,7 @@
#include "display_io.h" #include "display_io.h"
#include "irq.h" #include "irq.h"
#include "mpu.h"
__IO DISP_MEM_TYPE *const DISPLAY_CMD_ADDRESS = __IO DISP_MEM_TYPE *const DISPLAY_CMD_ADDRESS =
(__IO DISP_MEM_TYPE *const)((uint32_t)DISPLAY_MEMORY_BASE); (__IO DISP_MEM_TYPE *const)((uint32_t)DISPLAY_MEMORY_BASE);
@ -127,7 +128,9 @@ void display_io_init_fmc(void) {
normal_mode_timing.DataLatency = 2; // don't care normal_mode_timing.DataLatency = 2; // don't care
normal_mode_timing.AccessMode = FMC_ACCESS_MODE_A; normal_mode_timing.AccessMode = FMC_ACCESS_MODE_A;
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_FSMC_REGS);
HAL_SRAM_Init(&external_display_data_sram, &normal_mode_timing, NULL); HAL_SRAM_Init(&external_display_data_sram, &normal_mode_timing, NULL);
mpu_restore(mpu_mode);
} }
#ifdef DISPLAY_TE_INTERRUPT_HANDLER #ifdef DISPLAY_TE_INTERRUPT_HANDLER

View File

@ -22,6 +22,7 @@
#include "entropy.h" #include "entropy.h"
#include "flash_otp.h" #include "flash_otp.h"
#include "model.h" #include "model.h"
#include "mpu.h"
#include "rand.h" #include "rand.h"
#include "stm32u5xx_ll_utils.h" #include "stm32u5xx_ll_utils.h"
@ -29,6 +30,8 @@
static uint8_t g_hw_entropy[HW_ENTROPY_LEN]; static uint8_t g_hw_entropy[HW_ENTROPY_LEN];
void entropy_init(void) { void entropy_init(void) {
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP);
// collect entropy from UUID // collect entropy from UUID
uint32_t w = LL_GetUID_Word0(); uint32_t w = LL_GetUID_Word0();
memcpy(g_hw_entropy, &w, 4); memcpy(g_hw_entropy, &w, 4);
@ -37,6 +40,8 @@ void entropy_init(void) {
w = LL_GetUID_Word2(); w = LL_GetUID_Word2();
memcpy(g_hw_entropy + 8, &w, 4); memcpy(g_hw_entropy + 8, &w, 4);
mpu_restore(mpu_mode);
// set entropy in the OTP randomness block // set entropy in the OTP randomness block
if (secfalse == flash_otp_is_locked(FLASH_OTP_BLOCK_RANDOMNESS)) { if (secfalse == flash_otp_is_locked(FLASH_OTP_BLOCK_RANDOMNESS)) {
uint8_t entropy[FLASH_OTP_BLOCK_SIZE]; uint8_t entropy[FLASH_OTP_BLOCK_SIZE];

View File

@ -22,6 +22,7 @@
#include "flash_otp.h" #include "flash_otp.h"
#include "common.h" #include "common.h"
#include "flash.h" #include "flash.h"
#include "mpu.h"
void flash_otp_init() { void flash_otp_init() {
// intentionally left empty // intentionally left empty
@ -33,10 +34,16 @@ secbool flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data,
offset + datalen > FLASH_OTP_BLOCK_SIZE) { offset + datalen > FLASH_OTP_BLOCK_SIZE) {
return secfalse; return secfalse;
} }
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP);
for (uint8_t i = 0; i < datalen; i++) { for (uint8_t i = 0; i < datalen; i++) {
data[i] = *(__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE + data[i] = *(__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE +
offset + i); offset + i);
} }
mpu_restore(mpu_mode);
return sectrue; return sectrue;
} }
@ -49,6 +56,9 @@ secbool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data,
offset + datalen > FLASH_OTP_BLOCK_SIZE) { offset + datalen > FLASH_OTP_BLOCK_SIZE) {
return secfalse; return secfalse;
} }
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_OTP);
ensure(flash_unlock_write(), NULL); ensure(flash_unlock_write(), NULL);
for (uint8_t i = 0; i < datalen; i += 16) { for (uint8_t i = 0; i < datalen; i += 16) {
uint32_t address = uint32_t address =
@ -58,35 +68,60 @@ secbool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data,
NULL); NULL);
} }
ensure(flash_lock_write(), NULL); ensure(flash_lock_write(), NULL);
mpu_restore(mpu_mode);
return sectrue; return sectrue;
} }
secbool flash_otp_lock(uint8_t block) { 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 // check that all quadwords in the block have been written to
volatile uint8_t *addr = volatile uint8_t *addr =
(__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE); (__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; secbool qw_locked = secfalse;
for (uint8_t i = 0; i < FLASH_OTP_BLOCK_SIZE; i++) { for (uint8_t i = 0; i < FLASH_OTP_BLOCK_SIZE; i++) {
if (addr[i] != 0xFF) { if (addr[i] != 0xFF) {
qw_locked = sectrue; qw_locked = sectrue;
} }
if (i % 16 == 15 && qw_locked == secfalse) { if (i % 16 == 15 && qw_locked == secfalse) {
mpu_restore(mpu_mode);
return secfalse; return secfalse;
} }
} }
mpu_restore(mpu_mode);
return sectrue; return sectrue;
} }
secbool flash_otp_is_locked(uint8_t block) { 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 // considering block locked if any quadword in the block is non-0xFF
volatile uint8_t *addr = volatile uint8_t *addr =
(__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE); (__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++) { for (uint8_t i = 0; i < FLASH_OTP_BLOCK_SIZE; i++) {
if (addr[i] != 0xFF) { if (addr[i] != 0xFF) {
return sectrue; is_locked = sectrue;
break;
} }
} }
return secfalse;
mpu_restore(mpu_mode);
return is_locked;
} }

View File

@ -20,6 +20,7 @@
#include "monoctr.h" #include "monoctr.h"
#include "flash_area.h" #include "flash_area.h"
#include "model.h" #include "model.h"
#include "mpu.h"
#include "secret.h" #include "secret.h"
static int32_t get_offset(monoctr_type_t type) { static int32_t get_offset(monoctr_type_t type) {
@ -80,6 +81,8 @@ secbool monoctr_read(monoctr_type_t type, uint8_t *value) {
return secfalse; return secfalse;
} }
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET);
int counter = 0; int counter = 0;
int i = 0; int i = 0;
@ -111,10 +114,13 @@ secbool monoctr_read(monoctr_type_t type, uint8_t *value) {
if (not_cleared != sectrue) { if (not_cleared != sectrue) {
// monotonic counter is not valid // monotonic counter is not valid
mpu_restore(mpu_mode);
return secfalse; return secfalse;
} }
} }
mpu_restore(mpu_mode);
if (value != NULL) { if (value != NULL) {
*value = counter; *value = counter;
} else { } else {

View File

@ -19,8 +19,11 @@
#include STM32_HAL_H #include STM32_HAL_H
#include <stdbool.h> #include <stdbool.h>
#include "common.h" #include "common.h"
#include "model.h" #include "model.h"
#include "mpu.h"
#include "stm32u5xx_ll_cortex.h" #include "stm32u5xx_ll_cortex.h"
// region type // region type
@ -126,22 +129,11 @@ static void mpu_set_attributes(void) {
#error "Unknown MCU" #error "Unknown MCU"
#endif #endif
#define L1_REST_SIZE (FLASH_SIZE - (BOARDLOADER_SIZE + SECRET_SIZE))
#define L2_PREV_SIZE (SECRET_SIZE + BOARDLOADER_SIZE)
#define L2_REST_SIZE \
(FLASH_SIZE - (BOOTLOADER_SIZE + BOARDLOADER_SIZE + SECRET_SIZE))
#define L3_PREV_SIZE \
(STORAGE_SIZE + BOOTLOADER_SIZE + BOARDLOADER_SIZE + SECRET_SIZE)
#define ASSETS_START (FIRMWARE_START + FIRMWARE_SIZE) #define ASSETS_START (FIRMWARE_START + FIRMWARE_SIZE)
#define ASSETS_SIZE \ #define ASSETS_SIZE \
(FLASH_SIZE - (FIRMWARE_SIZE + BOOTLOADER_SIZE + BOARDLOADER_SIZE + \ (FLASH_SIZE - (FIRMWARE_SIZE + BOOTLOADER_SIZE + BOARDLOADER_SIZE + \
SECRET_SIZE + STORAGE_SIZE)) SECRET_SIZE + STORAGE_SIZE))
#define L3_PREV_SIZE_BLD (STORAGE_SIZE + BOOTLOADER_SIZE)
#ifdef STM32U585xx #ifdef STM32U585xx
#define GRAPHICS_START FMC_BANK1 #define GRAPHICS_START FMC_BANK1
#define GRAPHICS_SIZE SIZE_16M #define GRAPHICS_SIZE SIZE_16M
@ -152,106 +144,194 @@ static void mpu_set_attributes(void) {
#define OTP_AND_ID_SIZE 0x800 #define OTP_AND_ID_SIZE 0x800
void mpu_config_boardloader(void) { // clang-format on
HAL_MPU_Disable();
mpu_set_attributes(); #define KERNEL_RAM_START (SRAM2_BASE - SIZE_16K)
#define KERNEL_RAM_SIZE (SIZE_24K)
#define COREAPP_RAM1_START SRAM1_BASE
#define COREAPP_RAM1_SIZE (SIZE_192K - SIZE_16K)
#define COREAPP_RAM2_START (SRAM2_BASE + SIZE_8K)
#define COREAPP_RAM2_SIZE (SRAM_SIZE - (SIZE_192K + SIZE_8K))
typedef struct {
// Set if the driver is initialized
bool initialized;
// Current mode
mpu_mode_t mode;
} mpu_driver_t;
mpu_driver_t g_mpu_driver = {
.initialized = false,
.mode = MPU_MODE_DISABLED,
};
static void mpu_init_fixed_regions(void) {
// Regions #0 to #5 are fixed for all targets
// clang-format off // clang-format off
#if defined(BOARDLOADER)
// REGION ADDRESS SIZE TYPE WRITE UNPRIV // REGION ADDRESS SIZE TYPE WRITE UNPRIV
SET_REGION( 0, SECRET_START, SECRET_SIZE, FLASH_DATA, YES, NO ); // Secret SET_REGION( 0, BOARDLOADER_START, BOARDLOADER_SIZE, FLASH_CODE, NO, NO );
SET_REGION( 1, BOARDLOADER_START, BOARDLOADER_SIZE, FLASH_CODE, NO, NO ); // Boardloader code SET_REGION( 1, SRAM1_BASE, SRAM_SIZE, SRAM, YES, NO );
SET_REGION( 2, BOOTLOADER_START, L1_REST_SIZE, FLASH_DATA, YES, NO ); // Bootloader + Storage + Firmware SET_REGION( 2, BOOTLOADER_START, BOOTLOADER_SIZE, FLASH_DATA, YES, NO );
SET_REGION( 3, SRAM1_BASE, SRAM_SIZE, SRAM, YES, NO ); // SRAM1/2/3/5 SET_REGION( 3, FIRMWARE_START, FIRMWARE_SIZE, FLASH_DATA, YES, NO );
SET_REGION( 4, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, NO ); // Frame buffer or display interface DIS_REGION( 4 );
SET_REGION( 5, PERIPH_BASE_NS, SIZE_512M, PERIPHERAL, YES, NO ); // Peripherals SET_REGION( 5, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, NO );
#endif
#if defined(BOOTLOADER)
// REGION ADDRESS SIZE TYPE WRITE UNPRIV
SET_REGION( 0, BOOTLOADER_START, BOOTLOADER_SIZE, FLASH_CODE, NO, NO );
SET_REGION( 1, SRAM1_BASE, SRAM_SIZE, SRAM, YES, NO );
SET_REGION( 2, FIRMWARE_START, FIRMWARE_SIZE, FLASH_DATA, YES, NO );
DIS_REGION( 3 );
DIS_REGION( 4 );
SET_REGION( 5, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, NO );
#endif
#if defined(KERNEL)
// REGION ADDRESS SIZE TYPE WRITE UNPRIV
SET_REGION( 0, KERNEL_START, KERNEL_SIZE, FLASH_CODE, NO, NO );
SET_REGION( 1, KERNEL_RAM_START, KERNEL_RAM_SIZE, SRAM, YES, NO );
SET_REGION( 2, COREAPP_START, COREAPP_SIZE, FLASH_CODE, NO, YES );
SET_REGION( 3, COREAPP_RAM1_START, COREAPP_RAM1_SIZE, SRAM, YES, YES );
SET_REGION( 4, COREAPP_RAM2_START, COREAPP_RAM2_SIZE, SRAM, YES, YES );
SET_REGION( 5, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, YES );
#endif
#if defined(FIRMWARE)
// REGION ADDRESS SIZE TYPE WRITE UNPRIV
SET_REGION( 0, FIRMWARE_START, FIRMWARE_SIZE, FLASH_CODE, NO, NO );
SET_REGION( 1, SRAM1_BASE, SRAM_SIZE, SRAM, YES, NO );
DIS_REGION( 2 );
DIS_REGION( 3 );
DIS_REGION( 4 );
SET_REGION( 5, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, NO );
#endif
#if defined(TREZOR_PRODTEST)
SET_REGION( 0, FIRMWARE_START, 1024, FLASH_DATA, YES, NO );
SET_REGION( 1, FIRMWARE_START + 1024, FIRMWARE_SIZE - 1024, FLASH_CODE, NO, NO );
SET_REGION( 2, SRAM1_BASE, SRAM_SIZE, SRAM, YES, NO );
DIS_REGION( 3 );
DIS_REGION( 4 );
SET_REGION( 5, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, NO );
#endif
// Regions #6 and #7 are banked
DIS_REGION( 6 ); DIS_REGION( 6 );
SET_REGION( 7, SRAM4_BASE, SIZE_16K, SRAM, YES, NO ); // SRAM4 DIS_REGION( 7 );
// clang-format on // clang-format on
HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI);
} }
void mpu_config_bootloader(void) { void mpu_init(void) {
mpu_driver_t* drv = &g_mpu_driver;
if (drv->initialized) {
return;
}
irq_key_t irq_key = irq_lock();
HAL_MPU_Disable(); HAL_MPU_Disable();
mpu_set_attributes(); mpu_set_attributes();
// clang-format off
// REGION ADDRESS SIZE TYPE WRITE UNPRIV mpu_init_fixed_regions();
SET_REGION( 0, SECRET_START, L2_PREV_SIZE, FLASH_DATA, YES, NO ); // Secret + Boardloader
SET_REGION( 1, BOOTLOADER_START, BOOTLOADER_SIZE, FLASH_CODE, NO, NO ); // Bootloader code drv->mode = MPU_MODE_DISABLED;
SET_REGION( 2, STORAGE_START, L2_REST_SIZE, FLASH_DATA, YES, NO ); // Storage + Firmware drv->initialized = true;
SET_REGION( 3, SRAM1_BASE, SRAM_SIZE, SRAM, YES, NO ); // SRAM1/2/3/5
SET_REGION( 4, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, NO ); // Frame buffer or display interface irq_unlock(irq_key);
SET_REGION( 5, PERIPH_BASE_NS, SIZE_512M, PERIPHERAL, YES, NO ); // Peripherals
SET_REGION( 6, FLASH_OTP_BASE, FLASH_OTP_SIZE, FLASH_DATA, YES, NO ); // OTP
SET_REGION( 7, SRAM4_BASE, SIZE_16K, SRAM, YES, NO ); // SRAM4
// clang-format on
HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI);
} }
void mpu_config_firmware_initial(void) { mpu_mode_t mpu_get_mode(void) {
mpu_driver_t* drv = &g_mpu_driver;
if (!drv->initialized) {
return MPU_MODE_DISABLED;
}
return drv->mode;
}
mpu_mode_t mpu_reconfig(mpu_mode_t mode) {
mpu_driver_t* drv = &g_mpu_driver;
if (!drv->initialized) {
// Solves the issue when some IRQ handler tries to reconfigure
// MPU before it is initialized
return MPU_MODE_DISABLED;
}
irq_key_t irq_key = irq_lock();
HAL_MPU_Disable(); HAL_MPU_Disable();
mpu_set_attributes();
// Region #6 is banked
// clang-format off // clang-format off
// REGION ADDRESS SIZE TYPE WRITE UNPRIV switch (mode) {
SET_REGION( 0, BOOTLOADER_START, L3_PREV_SIZE_BLD, FLASH_DATA, YES, YES ); // Bootloader + Storage case MPU_MODE_DISABLED:
SET_REGION( 1, FIRMWARE_START, FIRMWARE_SIZE, FLASH_CODE, NO, YES ); // Firmware break;
SET_REGION( 2, ASSETS_START, ASSETS_SIZE, FLASH_DATA, YES, YES ); // Assets #if !defined(BOARDLOADER)
SET_REGION( 3, SRAM1_BASE, SRAM_SIZE, SRAM, YES, YES ); // SRAM1/2/3/5 case MPU_MODE_BOARDCAPS:
SET_REGION( 4, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, YES ); // Frame buffer or display interface // REGION ADDRESS SIZE TYPE WRITE UNPRIV
SET_REGION( 5, PERIPH_BASE_NS, SIZE_512M, PERIPHERAL, YES, YES ); // Peripherals SET_REGION( 6, BOARDLOADER_START, BOARDLOADER_SIZE, FLASH_DATA, NO, NO );
SET_REGION( 6, FLASH_OTP_BASE, SIZE_2K, FLASH_DATA, YES, YES ); // OTP break;
SET_REGION( 7, SRAM4_BASE, SIZE_16K, SRAM, YES, YES ); // SRAM4 #endif
#if !defined(BOOTLOADER) && !defined(BOARDLOADER)
case MPU_MODE_BOOTUPDATE:
SET_REGION( 6, BOOTLOADER_START, BOOTLOADER_SIZE, FLASH_DATA, YES, NO );
break;
#endif
case MPU_MODE_OTP:
SET_REGION( 6, FLASH_OTP_BASE, OTP_AND_ID_SIZE, FLASH_DATA, NO, NO );
break;
case MPU_MODE_SECRET:
SET_REGION( 6, SECRET_START, SECRET_SIZE, FLASH_DATA, YES, NO );
break;
case MPU_MODE_STORAGE:
SET_REGION( 6, STORAGE_START, STORAGE_SIZE, FLASH_DATA, YES, NO );
break;
case MPU_MODE_ASSETS:
SET_REGION( 6, ASSETS_START, ASSETS_SIZE, FLASH_DATA, YES, NO );
break;
case MPU_MODE_APP:
SET_REGION( 6, ASSETS_START, ASSETS_SIZE, FLASH_DATA, NO, YES );
break;
default:
DIS_REGION( 6 );
break;
}
// clang-format on // clang-format on
HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI);
// Region #7 is banked
// clang-format off
switch (mode) {
case MPU_MODE_APP:
// REGION ADDRESS SIZE TYPE WRITE UNPRIV
// DMA2D peripherals (Unprivileged, Read-Write, Non-Executable)
SET_REGION( 7, 0x5002B000, SIZE_3K, PERIPHERAL, YES, YES );
break;
default:
// All peripherals (Privileged, Read-Write, Non-Executable)
SET_REGION( 7, PERIPH_BASE_NS, SIZE_512M, PERIPHERAL, YES, NO );
break;
}
// clang-format on
if (mode != MPU_MODE_DISABLED) {
HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI);
}
mpu_mode_t prev_mode = drv->mode;
drv->mode = mode;
irq_unlock(irq_key);
return prev_mode;
} }
void mpu_config_firmware(void) { void mpu_restore(mpu_mode_t mode) { mpu_reconfig(mode); }
HAL_MPU_Disable();
mpu_set_attributes();
// clang-format off
// REGION ADDRESS SIZE TYPE WRITE UNPRIV
SET_REGION( 0, STORAGE_START, STORAGE_SIZE, FLASH_DATA, YES, YES ); // Storage
SET_REGION( 1, FIRMWARE_START, FIRMWARE_SIZE, FLASH_CODE, NO, YES ); // Firmware
SET_REGION( 2, ASSETS_START, ASSETS_SIZE, FLASH_DATA, YES, YES ); // Assets
SET_REGION( 3, SRAM1_BASE, SRAM_SIZE, SRAM, YES, YES ); // SRAM1/2/3/5
SET_REGION( 4, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, YES ); // Frame buffer or display interface
SET_REGION( 5, PERIPH_BASE_NS, SIZE_512M, PERIPHERAL, YES, YES ); // Peripherals
SET_REGION( 6, FLASH_OTP_BASE, FLASH_OTP_SIZE, FLASH_DATA, YES, YES ); // OTP
SET_REGION( 7, SRAM4_BASE, SIZE_16K, SRAM, YES, YES ); // SRAM4
// clang-format on
HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI);
}
void mpu_config_prodtest_initial(void) {
HAL_MPU_Disable();
mpu_set_attributes();
// clang-format off
// REGION ADDRESS SIZE TYPE WRITE UNPRIV
SET_REGION( 0, FLASH_BASE, L3_PREV_SIZE, FLASH_DATA, YES, YES ); // Secret, Bld, Storage
SET_REGION( 1, FIRMWARE_START, FIRMWARE_SIZE, FLASH_CODE, NO, YES ); // Firmware
SET_REGION( 2, ASSETS_START, ASSETS_SIZE, FLASH_DATA, YES, YES ); // Assets
SET_REGION( 3, SRAM1_BASE, SRAM_SIZE, SRAM, YES, YES ); // SRAM1/2/3/5
SET_REGION( 4, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, YES ); // Frame buffer or display interface
SET_REGION( 5, PERIPH_BASE_NS, SIZE_512M, PERIPHERAL, YES, YES ); // Peripherals
SET_REGION( 6, FLASH_OTP_BASE, FLASH_OTP_SIZE, FLASH_DATA, YES, YES ); // OTP
SET_REGION( 7, SRAM4_BASE, SIZE_16K, SRAM, YES, YES ); // SRAM4
// clang-format on
HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI);
}
void mpu_config_prodtest(void) {
HAL_MPU_Disable();
mpu_set_attributes();
// clang-format off
// REGION ADDRESS SIZE TYPE WRITE UNPRIV
SET_REGION( 0, STORAGE_START, STORAGE_SIZE, FLASH_DATA, YES, YES ); // Storage
SET_REGION( 1, FIRMWARE_START, FIRMWARE_SIZE, FLASH_CODE, YES, YES ); // Firmware
SET_REGION( 2, ASSETS_START, ASSETS_SIZE, FLASH_DATA, YES, YES ); // Assets
SET_REGION( 3, SRAM1_BASE, SRAM_SIZE, SRAM, YES, YES ); // SRAM1/2/3/5
SET_REGION( 4, GRAPHICS_START, GRAPHICS_SIZE, SRAM, YES, YES ); // Frame buffer or display interface
SET_REGION( 5, PERIPH_BASE_NS, SIZE_512M, PERIPHERAL, YES, YES ); // Peripherals
SET_REGION( 6, FLASH_OTP_BASE, OTP_AND_ID_SIZE, FLASH_DATA, YES, YES ); // OTP + device ID
SET_REGION( 7, SRAM4_BASE, SIZE_16K, SRAM, YES, YES ); // SRAM4
// clang-format on
HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI);
}
void mpu_config_off(void) { HAL_MPU_Disable(); }

View File

@ -4,8 +4,10 @@
#include "bootutils.h" #include "bootutils.h"
#include "common.h" #include "common.h"
#include "flash.h" #include "flash.h"
#include "flash_utils.h"
#include "memzero.h" #include "memzero.h"
#include "model.h" #include "model.h"
#include "mpu.h"
#include "rng.h" #include "rng.h"
#include "secure_aes.h" #include "secure_aes.h"
@ -19,17 +21,21 @@ secbool secret_verify_header(void) {
return secfalse; return secfalse;
} }
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET);
bootloader_locked = bootloader_locked =
memcmp(addr, SECRET_HEADER_MAGIC, sizeof(SECRET_HEADER_MAGIC)) == 0 memcmp(addr, SECRET_HEADER_MAGIC, sizeof(SECRET_HEADER_MAGIC)) == 0
? sectrue ? sectrue
: secfalse; : secfalse;
mpu_restore(mpu_mode);
return bootloader_locked; return bootloader_locked;
} }
secbool secret_ensure_initialized(void) { secbool secret_ensure_initialized(void) {
if (sectrue != secret_verify_header()) { if (sectrue != secret_verify_header()) {
ensure(flash_area_erase_bulk(STORAGE_AREAS, STORAGE_AREAS_COUNT, NULL), ensure(erase_storage(NULL), "erase storage failed");
"erase storage failed");
secret_erase(); secret_erase();
secret_write_header(); secret_write_header();
return secfalse; return secfalse;
@ -58,6 +64,7 @@ void secret_write_header(void) {
} }
void secret_write(const uint8_t *data, uint32_t offset, uint32_t len) { void secret_write(const uint8_t *data, uint32_t offset, uint32_t len) {
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET);
ensure(flash_unlock_write(), "secret write"); ensure(flash_unlock_write(), "secret write");
for (int i = 0; i < len / 16; i++) { for (int i = 0; i < len / 16; i++) {
ensure(flash_area_write_quadword(&SECRET_AREA, offset + (i * 16), ensure(flash_area_write_quadword(&SECRET_AREA, offset + (i * 16),
@ -65,6 +72,7 @@ void secret_write(const uint8_t *data, uint32_t offset, uint32_t len) {
"secret write"); "secret write");
} }
ensure(flash_lock_write(), "secret write"); ensure(flash_lock_write(), "secret write");
mpu_restore(mpu_mode);
} }
secbool secret_read(uint8_t *data, uint32_t offset, uint32_t len) { secbool secret_read(uint8_t *data, uint32_t offset, uint32_t len) {
@ -76,7 +84,10 @@ secbool secret_read(uint8_t *data, uint32_t offset, uint32_t len) {
if (addr == NULL) { if (addr == NULL) {
return secfalse; return secfalse;
} }
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET);
memcpy(data, addr, len); memcpy(data, addr, len);
mpu_restore(mpu_mode);
return sectrue; return sectrue;
} }
@ -106,6 +117,8 @@ static secbool secret_present(uint32_t offset, uint32_t len) {
return secfalse; return secfalse;
} }
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET);
int secret_empty_bytes = 0; int secret_empty_bytes = 0;
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
@ -115,6 +128,9 @@ static secbool secret_present(uint32_t offset, uint32_t len) {
secret_empty_bytes++; secret_empty_bytes++;
} }
} }
mpu_restore(mpu_mode);
return sectrue * (secret_empty_bytes != len); return sectrue * (secret_empty_bytes != len);
} }
@ -152,6 +168,8 @@ static void secret_bhk_load(void) {
} }
void secret_bhk_regenerate(void) { void secret_bhk_regenerate(void) {
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET);
ensure(flash_area_erase(&BHK_AREA, NULL), "Failed regenerating BHK"); ensure(flash_area_erase(&BHK_AREA, NULL), "Failed regenerating BHK");
ensure(flash_unlock_write(), "Failed regenerating BHK"); ensure(flash_unlock_write(), "Failed regenerating BHK");
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
@ -164,6 +182,9 @@ void secret_bhk_regenerate(void) {
memzero(val, sizeof(val)); memzero(val, sizeof(val));
ensure(res, "Failed regenerating BHK"); ensure(res, "Failed regenerating BHK");
} }
mpu_restore(mpu_mode);
ensure(flash_lock_write(), "Failed regenerating BHK"); ensure(flash_lock_write(), "Failed regenerating BHK");
} }
@ -187,6 +208,8 @@ secbool secret_optiga_writable(void) {
return secfalse; return secfalse;
} }
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET);
int secret_empty_bytes = 0; int secret_empty_bytes = 0;
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
@ -196,6 +219,9 @@ secbool secret_optiga_writable(void) {
secret_empty_bytes++; secret_empty_bytes++;
} }
} }
mpu_restore(mpu_mode);
return sectrue * (secret_empty_bytes == len); return sectrue * (secret_empty_bytes == len);
} }
@ -272,7 +298,9 @@ void secret_optiga_erase(void) {
} }
void secret_erase(void) { void secret_erase(void) {
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_SECRET);
ensure(flash_area_erase(&SECRET_AREA, NULL), "secret erase"); ensure(flash_area_erase(&SECRET_AREA, NULL), "secret erase");
mpu_restore(mpu_mode);
} }
void secret_prepare_fw(secbool allow_run_with_secret, secbool trust_all) { void secret_prepare_fw(secbool allow_run_with_secret, secbool trust_all) {

View File

@ -0,0 +1,30 @@
/*
* 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 "mpu.h"
void mpu_init(void) {
// MPU functions are not fully implemented in Emulator
}
mpu_mode_t mpu_get_mode(void) { return MPU_MODE_DISABLED; }
mpu_mode_t mpu_reconfig(mpu_mode_t mode) { return MPU_MODE_DISABLED; }
void mpu_restore(mpu_mode_t mode) {}