Skip to content

Commit 93d6211

Browse files
authored
Merge pull request #52 from danielinux/mpu
Added support for memory protection on ARM using MPU
2 parents ad9b17d + dd17aa7 commit 93d6211

3 files changed

Lines changed: 146 additions & 15 deletions

File tree

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ ifeq ($(V),0)
159159
Q=@
160160
endif
161161

162+
ifeq ($(NO_MPU),1)
163+
CFLAGS+=-DWOLFBOOT_NO_MPU
164+
endif
165+
162166
ifeq ($(VTOR),0)
163167
CFLAGS+=-DNO_VTOR
164168
endif

src/boot_arm.c

Lines changed: 140 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "loader.h"
2626
#include "wolfboot/wolfboot.h"
2727

28+
extern unsigned int _start_text;
2829
extern unsigned int _stored_data;
2930
extern unsigned int _start_data;
3031
extern unsigned int _end_data;
@@ -35,6 +36,130 @@ extern uint32_t *END_STACK;
3536

3637
extern void main(void);
3738

39+
#ifndef WOLFBOOT_NO_MPU
40+
#define MPU_BASE (0xE000ED90)
41+
#define MPU_TYPE *((volatile uint32_t *)(MPU_BASE + 0x00))
42+
#define MPU_CTRL *((volatile uint32_t *)(MPU_BASE + 0x04))
43+
#define MPU_RNR *((volatile uint32_t *)(MPU_BASE + 0x08))
44+
#define MPU_RBAR *((volatile uint32_t *)(MPU_BASE + 0x0C))
45+
#define MPU_RASR *((volatile uint32_t *)(MPU_BASE + 0x10))
46+
47+
#define MPU_RASR_ENABLE (1 << 0)
48+
#define MPU_RASR_ATTR_XN (1 << 28)
49+
#define MPU_RASR_ATTR_AP (7 << 24)
50+
#define MPU_RASR_ATTR_AP_PNO_UNO (0 << 24)
51+
#define MPU_RASR_ATTR_AP_PRW_UNO (1 << 24)
52+
#define MPU_RASR_ATTR_AP_PRW_URO (2 << 24)
53+
#define MPU_RASR_ATTR_AP_PRW_URW (3 << 24)
54+
#define MPU_RASR_ATTR_AP_PRO_UNO (5 << 24)
55+
#define MPU_RASR_ATTR_AP_PRO_URO (6 << 24)
56+
#define MPU_RASR_ATTR_TEX (7 << 19)
57+
#define MPU_RASR_ATTR_S (1 << 18)
58+
#define MPU_RASR_ATTR_C (1 << 17)
59+
#define MPU_RASR_ATTR_B (1 << 16)
60+
#define MPU_RASR_ATTR_SCB (7 << 16)
61+
62+
static int mpu_is_on = 0;
63+
64+
static void mpu_setaddr(int region, uint32_t addr)
65+
{
66+
MPU_RNR = region;
67+
MPU_RBAR = addr;
68+
}
69+
70+
static void mpu_setattr(int region, uint32_t attr)
71+
{
72+
MPU_RNR = region;
73+
MPU_RASR = attr;
74+
}
75+
76+
static void mpu_on(void)
77+
{
78+
if (mpu_is_on)
79+
return;
80+
if (MPU_TYPE == 0)
81+
return;
82+
MPU_CTRL = 1;
83+
mpu_is_on = 1;
84+
}
85+
86+
#define MPUSIZE_8K (0x0c << 1)
87+
#define MPUSIZE_16K (0x0d << 1)
88+
#define MPUSIZE_32K (0x0e << 1)
89+
#define MPUSIZE_64K (0x0f << 1)
90+
/* ... */
91+
#define MPUSIZE_256M (0x1b << 1)
92+
#define MPUSIZE_512M (0x1c << 1)
93+
#define MPUSIZE_1G (0x1d << 1)
94+
#define MPUSIZE_4G (0x1f << 1)
95+
#define MPUSIZE_ERR (0xff << 1)
96+
static uint32_t mpusize(uint32_t size)
97+
{
98+
if (size <= (8 * 1024))
99+
return MPUSIZE_8K;
100+
if (size <= (16 * 1024))
101+
return MPUSIZE_16K;
102+
if (size <= (32 * 1024))
103+
return MPUSIZE_32K;
104+
if (size <= (64 * 1024))
105+
return MPUSIZE_64K;
106+
return MPUSIZE_ERR;
107+
}
108+
109+
static void mpu_init(void)
110+
{
111+
uint32_t wolfboot_flash_size = (uint32_t)&_stored_data - (uint32_t)&_start_text;
112+
uint32_t wolfboot_mpusize;
113+
uint32_t ram_base = (uint32_t)(&_start_data);
114+
uint32_t flash_base = (uint32_t)(&_start_text);
115+
if (MPU_TYPE == 0)
116+
return;
117+
118+
/* Read access to address space with XN */
119+
mpu_setaddr(0, 0);
120+
mpu_setattr(0, MPUSIZE_4G | MPU_RASR_ENABLE | MPU_RASR_ATTR_SCB | MPU_RASR_ATTR_AP_PRO_UNO | MPU_RASR_ATTR_XN);
121+
122+
wolfboot_mpusize = mpusize(wolfboot_flash_size);
123+
if (wolfboot_mpusize == MPUSIZE_ERR)
124+
return;
125+
126+
/* Text in Read-only memory */
127+
mpu_setaddr(1, flash_base);
128+
mpu_setattr(1, wolfboot_mpusize | MPU_RASR_ENABLE | MPU_RASR_ATTR_SCB | MPU_RASR_ATTR_AP_PRO_UNO);
129+
130+
/* Data in r/w memory */
131+
mpu_setaddr(2, ram_base);
132+
#ifdef RAM_CODE
133+
mpu_setattr(2, MPUSIZE_64K | MPU_RASR_ENABLE | MPU_RASR_ATTR_SCB | MPU_RASR_ATTR_AP_PRW_UNO);
134+
#else
135+
mpu_setattr(2, MPUSIZE_64K | MPU_RASR_ENABLE | MPU_RASR_ATTR_SCB | MPU_RASR_ATTR_AP_PRW_UNO | MPU_RASR_ATTR_XN);
136+
#endif
137+
138+
/* Peripherals 0x40000000:0x5FFFFFFF (512MB)*/
139+
mpu_setaddr(5, 0x40000000);
140+
mpu_setattr(5, MPUSIZE_512M | MPU_RASR_ENABLE | MPU_RASR_ATTR_S | MPU_RASR_ATTR_B | MPU_RASR_ATTR_AP_PRW_UNO | MPU_RASR_ATTR_XN);
141+
142+
/* External peripherals 0xA0000000:0xCFFFFFFF (1GB)*/
143+
mpu_setaddr(6, 0xA0000000);
144+
mpu_setattr(6, MPUSIZE_1G | MPU_RASR_ENABLE | MPU_RASR_ATTR_S | MPU_RASR_ATTR_B | MPU_RASR_ATTR_AP_PRW_UNO | MPU_RASR_ATTR_XN);
145+
146+
/* System control 0xE0000000:0xEFFFFFF */
147+
mpu_setaddr(7, 0xE0000000);
148+
mpu_setattr(7, MPUSIZE_256M | MPU_RASR_ENABLE | MPU_RASR_ATTR_S | MPU_RASR_ATTR_B | MPU_RASR_ATTR_AP_PRW_UNO | MPU_RASR_ATTR_XN);
149+
mpu_on();
150+
151+
}
152+
153+
static void mpu_off(void)
154+
{
155+
mpu_is_on = 0;
156+
MPU_CTRL = 0;
157+
}
158+
#else /* NO MPU */
159+
#define mpu_init() do{}while(0)
160+
#define mpu_off() do{}while(0)
161+
#endif /* NO MPU */
162+
38163

39164
void isr_reset(void) {
40165
register unsigned int *src, *dst;
@@ -62,6 +187,7 @@ void isr_reset(void) {
62187
dst++;
63188
}
64189

190+
mpu_init();
65191
/* Run the program! */
66192
main();
67193
}
@@ -94,7 +220,7 @@ static uint32_t app_end_stack;
94220

95221
void RAMFUNCTION do_boot(const uint32_t *app_offset)
96222
{
97-
223+
mpu_off();
98224
#ifndef NO_VTOR
99225
/* Disable interrupts */
100226
asm volatile("cpsid i");
@@ -125,19 +251,19 @@ typedef void(*NMIHANDLER)(void);
125251
__attribute__ ((section(".isr_vector")))
126252
void (* const IV[])(void) =
127253
{
128-
(void (*)(void))(&END_STACK),
129-
isr_reset, // Reset
130-
isr_NMI, // NMI
131-
isr_fault, // HardFault
132-
isr_fault, // MemFault
133-
isr_fault, // BusFault
134-
isr_fault, // UsageFault
135-
0, 0, 0, 0, // 4x reserved
136-
isr_empty, // SVC
137-
isr_empty, // DebugMonitor
138-
0, // reserved
139-
isr_empty, // PendSV
140-
isr_empty, // SysTick
254+
(void (*)(void))(&END_STACK),
255+
isr_reset, // Reset
256+
isr_NMI, // NMI
257+
isr_fault, // HardFault
258+
isr_fault, // MemFault
259+
isr_fault, // BusFault
260+
isr_fault, // UsageFault
261+
0, 0, 0, 0, // 4x reserved
262+
isr_empty, // SVC
263+
isr_empty, // DebugMonitor
264+
0, // reserved
265+
isr_empty, // PendSV
266+
isr_empty, // SysTick
141267

142268
isr_empty,
143269
isr_empty,

tools/config.mk

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ ifeq ($(ARCH),)
2525
NVM_FLASH_WRITEONCE?=0
2626
WOLFBOOT_VERSION?=0
2727
V?=0
28+
NO_MPU?=0
2829
SPMATH?=1
2930
RAM_CODE?=0
3031
DUALBANK_SWAP?=0
@@ -46,7 +47,7 @@ endif
4647
CONFIG_VARS:= ARCH TARGET SIGN HASH MCUXPRESSO MCUXPRESSO_CPU MCUXPRESSO_DRIVERS \
4748
MCUXPRESSO_CMSIS FREEDOM_E_SDK STM32CUBE CYPRESS_PDL CYPRESS_CORE_LIB CYPRESS_TARGET_LIB DEBUG VTOR \
4849
CORTEX_M0 NO_ASM EXT_FLASH SPI_FLASH NO_XIP UART_FLASH ALLOW_DOWNGRADE NVM_FLASH_WRITEONCE \
49-
WOLFBOOT_VERSION V \
50+
WOLFBOOT_VERSION V NO_MPU \
5051
SPMATH RAM_CODE DUALBANK_SWAP IMAGE_HEADER_SIZE PKA WOLFTPM \
5152
WOLFBOOT_PARTITION_SIZE WOLFBOOT_SECTOR_SIZE \
5253
WOLFBOOT_PARTITION_BOOT_ADDRESS WOLFBOOT_PARTITION_UPDATE_ADDRESS \

0 commit comments

Comments
 (0)