1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-07-03 21:32:33 +00:00

feat(core): support mpu region setup per applet

[no changelog]
This commit is contained in:
cepetr 2025-05-27 12:06:45 +02:00 committed by cepetr
parent a48abdb577
commit a133a01a1f
7 changed files with 89 additions and 49 deletions

View File

@ -17,8 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TREZORHAL_MPU_H
#define TREZORHAL_MPU_H
#pragma once
#include <trezor_types.h>
@ -68,6 +67,28 @@ mpu_mode_t mpu_reconfig(mpu_mode_t mode);
// Same as `mpu_reconfig()`, but with a more descriptive name.
void mpu_restore(mpu_mode_t mode);
typedef struct {
uint32_t start;
uint32_t size;
} mpu_area_t;
// Applet memory layout
typedef struct {
// Read/write data area #1
mpu_area_t data1;
// Read/write data area #2
mpu_area_t data2;
// Read-only code area #1
mpu_area_t code1;
// Read-only code area #2
mpu_area_t code2;
} applet_layout_t;
// Sets the MPU to allow unprivileged access to the given applet
// (just one applet at a time can be visible)
void mpu_set_active_applet(applet_layout_t* layout);
// Sets the MPU to allow access to the
// framebuffer at the given address and size.
//
@ -83,5 +104,3 @@ void mpu_set_active_fb(const void* addr, size_t size);
bool mpu_inside_active_fb(const void* addr, size_t size);
#endif // KERNEL_MODE
#endif // TREZORHAL_MPU_H

View File

@ -218,6 +218,10 @@ mpu_mode_t mpu_get_mode(void) {
return drv->mode;
}
void mpu_set_active_applet(applet_layout_t* layout) {
// On STM32F4 one coreapp applet is allowed to run at a time
}
void mpu_set_active_fb(const void* addr, size_t size) {
mpu_driver_t* drv = &g_mpu_driver;

View File

@ -152,24 +152,12 @@ extern uint8_t _uflash_start;
extern uint8_t _uflash_end;
#define KERNEL_FLASH_U_START (uint32_t) & _uflash_start
#define KERNEL_FLASH_U_SIZE ((uint32_t) & _uflash_end - KERNEL_FLASH_U_START)
#define KERNEL_FLASH_SIZE (KERNEL_SIZE - KERNEL_FLASH_U_SIZE)
#define COREAPP_FLASH_START \
(COREAPP_CODE_ALIGN(KERNEL_FLASH_START + KERNEL_SIZE) - KERNEL_FLASH_U_SIZE)
#else
#define KERNEL_FLASH_SIZE KERNEL_SIZE
#define COREAPP_FLASH_START \
(COREAPP_CODE_ALIGN(KERNEL_FLASH_START + KERNEL_SIZE))
#endif
#define COREAPP_FLASH_SIZE \
(FIRMWARE_MAXSIZE - (COREAPP_FLASH_START - FIRMWARE_START))
#endif
#endif // KERNEL
typedef struct {
// Set if the driver is initialized
@ -224,13 +212,9 @@ static void mpu_init_fixed_regions(void) {
// REGION ADDRESS SIZE TYPE WRITE UNPRIV
SET_REGRUN( 0, KERNEL_FLASH_START, KERNEL_FLASH_SIZE, FLASH_CODE, NO, NO ); // Kernel Code
SET_REGION( 1, MAIN_RAM_START, MAIN_RAM_SIZE, SRAM, YES, NO ); // Kernel RAM
SET_REGRUN( 2, COREAPP_FLASH_START, COREAPP_FLASH_SIZE, FLASH_CODE, NO, YES ); // CoreApp Code
SET_REGION( 3, AUX1_RAM_START, AUX1_RAM_SIZE, SRAM, YES, YES ); // CoraApp RAM
#ifdef STM32U585xx
SET_REGION( 4, AUX2_RAM_START, AUX2_RAM_SIZE, SRAM, YES, YES ); // CoraAPP RAM2
#else
DIS_REGION( 4 );
#endif
DIS_REGION( 2 ); // reserved for applets
DIS_REGION( 3 ); // reserved for applets
DIS_REGION( 4 ); // reserved for applets
#elif defined(FIRMWARE)
// REGION ADDRESS SIZE TYPE WRITE UNPRIV
@ -288,6 +272,50 @@ mpu_mode_t mpu_get_mode(void) {
return drv->mode;
}
void mpu_set_active_applet(applet_layout_t* layout) {
mpu_driver_t* drv = &g_mpu_driver;
if (!drv->initialized) {
return;
}
irq_key_t irq_key = irq_lock();
mpu_disable();
if (layout != NULL) {
// clang-format off
if (layout->code1.start != 0 && layout->code1.size != 0) {
SET_REGRUN( 2, layout->code1.start, layout->code1.size, FLASH_CODE, NO, YES );
} else {
DIS_REGION( 2 );
}
if (layout->data1.start != 0 && layout->data1.size != 0) {
SET_REGRUN( 3, layout->data1.start, layout->data1.size, SRAM, YES, YES );
} else {
DIS_REGION( 3 );
}
if (layout->data2.start != 0 && layout->data2.size != 0) {
SET_REGRUN( 4, layout->data2.start, layout->data2.size, SRAM, YES, YES );
} else {
DIS_REGION( 4 );
}
// clang-format on
} else {
DIS_REGION(2);
DIS_REGION(3);
DIS_REGION(4);
}
if (drv->mode != MPU_MODE_DISABLED) {
mpu_enable();
}
irq_unlock(irq_key);
}
void mpu_set_active_fb(const void* addr, size_t size) {
mpu_driver_t* drv = &g_mpu_driver;

View File

@ -30,7 +30,7 @@
#ifdef KERNEL
static inline bool inside_area(const void *addr, size_t len,
const applet_memory_t *area) {
const mpu_area_t *area) {
return ((uintptr_t)addr >= area->start) &&
((uintptr_t)addr + len <= area->start + area->size);
}
@ -73,7 +73,7 @@ bool probe_read_access(const void *addr, size_t len) {
return true;
}
static const applet_memory_t assets = {
static const mpu_area_t assets = {
.start = ASSETS_START,
.size = ASSETS_MAXSIZE,
};

View File

@ -17,8 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TREZORHAL_APPLET_H
#define TREZORHAL_APPLET_H
#pragma once
#include <trezor_types.h>
@ -29,32 +28,14 @@
// Applet entry point
typedef void (*applet_startup_t)(const char* args, uint32_t random);
typedef struct {
uint32_t start;
uint32_t size;
} applet_memory_t;
// Applet header found at the beginning of the applet binary
typedef struct {
// Stack area
applet_memory_t stack;
mpu_area_t stack;
// Applet entry point
applet_startup_t startup;
} applet_header_t;
// Applet memory layout
typedef struct {
// Read/write data area #1
applet_memory_t data1;
// Read/write data area #2
applet_memory_t data2;
// Read-only code area #1
applet_memory_t code1;
// Read-only code area #2
applet_memory_t code2;
} applet_layout_t;
// Applet privileges
typedef struct {
bool assets_area_access;
@ -102,5 +83,3 @@ bool applet_is_alive(applet_t* applet);
applet_t* applet_active(void);
#endif // KERNEL
#endif // TREZORHAL_APPLET_H

View File

@ -42,6 +42,8 @@ void applet_init(applet_t* applet, applet_header_t* header,
}
static void applet_clear_memory(applet_t* applet) {
mpu_set_active_applet(&applet->layout);
if (applet->layout.data1.size > 0) {
memset((void*)applet->layout.data1.start, 0, applet->layout.data1.size);
}

View File

@ -22,6 +22,7 @@
#include <trezor_bsp.h>
#include <trezor_rtl.h>
#include <sys/applet.h>
#include <sys/bootutils.h>
#include <sys/irq.h>
#include <sys/linker_utils.h>
@ -432,6 +433,13 @@ __attribute((no_stack_protector, used)) static uint32_t scheduler_pendsv(
// Setup the MPU for the new task
mpu_reconfig(next_task->mpu_mode);
#ifdef KERNEL
if (next_task->applet != NULL) {
applet_t* applet = (applet_t*)next_task->applet;
mpu_set_active_applet(&applet->layout);
}
#endif
IRQ_LOG_EXIT();
return (uint32_t)next_task;