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:
parent
8fab22522a
commit
7f3cff04f1
@ -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',
|
||||||
|
@ -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',
|
||||||
|
@ -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',
|
||||||
|
@ -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',
|
||||||
|
@ -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',
|
||||||
|
@ -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',
|
||||||
|
@ -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));
|
||||||
|
@ -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]);
|
||||||
|
@ -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
|
||||||
|
@ -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),
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
|
@ -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");
|
||||||
|
@ -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
|
||||||
|
105
core/embed/lib/flash_utils.c
Normal file
105
core/embed/lib/flash_utils.c
Normal 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);
|
||||||
|
}
|
46
core/embed/lib/flash_utils.h
Normal file
46
core/embed/lib/flash_utils.h
Normal 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
|
@ -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) {
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
@ -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,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -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,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
@ -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,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
@ -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,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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 (;;)
|
||||||
;
|
;
|
||||||
|
@ -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];
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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");
|
|
||||||
}
|
|
||||||
|
@ -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]) {
|
||||||
|
@ -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
|
||||||
|
@ -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];
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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(); }
|
|
||||||
|
@ -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) {
|
||||||
|
30
core/embed/trezorhal/unix/mpu.c
Normal file
30
core/embed/trezorhal/unix/mpu.c
Normal 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) {}
|
Loading…
Reference in New Issue
Block a user