Skip to content

Commit 23892fb

Browse files
committed
fix: wrap printf in EBOOT_ENABLE_PRINTF guard for bare-metal safety
1 parent c029aca commit 23892fb

1 file changed

Lines changed: 180 additions & 168 deletions

File tree

core/mpu_boot.c

Lines changed: 180 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -1,168 +1,180 @@
1-
/**
2-
* @file mpu_boot.c
3-
* @brief MPU configuration during boot
4-
*/
5-
6-
#include "eos_mpu_boot.h"
7-
#include <string.h>
8-
#include <stdio.h>
9-
10-
int eos_mpu_init(eos_mpu_ctx_t *ctx)
11-
{
12-
if (!ctx) return -1;
13-
memset(ctx, 0, sizeof(*ctx));
14-
ctx->hw_regions = 8; /* Default for Cortex-M4/M7 */
15-
return 0;
16-
}
17-
18-
int eos_mpu_add_region(eos_mpu_ctx_t *ctx, uint32_t base, uint32_t size,
19-
eos_mpu_access_t access, bool exec, bool cache)
20-
{
21-
if (!ctx || ctx->count >= EOS_MPU_MAX_REGIONS) return -1;
22-
if (ctx->count >= ctx->hw_regions) return -1;
23-
24-
eos_mpu_region_t *r = &ctx->regions[ctx->count++];
25-
r->base_addr = base;
26-
r->size = size;
27-
r->access = access;
28-
r->executable = exec;
29-
r->cacheable = cache;
30-
r->bufferable = cache;
31-
r->shareable = false;
32-
r->enabled = true;
33-
return 0;
34-
}
35-
36-
int eos_mpu_set_default(eos_mpu_ctx_t *ctx)
37-
{
38-
if (!ctx) return -1;
39-
ctx->count = 0;
40-
41-
/* Flash — read + execute, cacheable */
42-
eos_mpu_add_region(ctx, 0x08000000, 0x200000, EOS_MPU_FULL_RO, true, true);
43-
/* RAM — read + write, no execute, cacheable */
44-
eos_mpu_add_region(ctx, 0x20000000, 0x100000, EOS_MPU_FULL_RW, false, true);
45-
/* Peripherals — read + write, no execute, no cache */
46-
eos_mpu_add_region(ctx, 0x40000000, 0x20000000, EOS_MPU_FULL_RW, false, false);
47-
/* System — privileged only */
48-
eos_mpu_add_region(ctx, 0xE0000000, 0x10000, EOS_MPU_PRIV_RW, false, false);
49-
50-
return 0;
51-
}
52-
53-
int eos_mpu_apply(const eos_mpu_ctx_t *ctx)
54-
{
55-
if (!ctx) return -1;
56-
57-
/* ARM Cortex-M MPU programming:
58-
* 1. Disable MPU
59-
* 2. Program each region (RBAR + RASR registers)
60-
* 3. Enable MPU with PRIVDEFENA
61-
*
62-
* Actual register writes are platform-specific. */
63-
64-
#if defined(__ARM_ARCH) && (__ARM_ARCH <= 7) && !defined(__aarch64__)
65-
/* MPU->CTRL disable */
66-
*((volatile uint32_t *)0xE000ED94) = 0;
67-
68-
for (int i = 0; i < ctx->count; i++) {
69-
const eos_mpu_region_t *r = &ctx->regions[i];
70-
if (!r->enabled) continue;
71-
72-
/* Calculate region size encoding (log2 - 1) */
73-
uint32_t size_bits = 0;
74-
uint32_t sz = r->size;
75-
while (sz > 1) { sz >>= 1; size_bits++; }
76-
77-
uint32_t rbar = r->base_addr | (1 << 4) | i;
78-
uint32_t rasr = (r->access << 24) | (size_bits << 1) | 1;
79-
if (!r->executable) rasr |= (1 << 28);
80-
if (r->cacheable) rasr |= (1 << 17);
81-
if (r->bufferable) rasr |= (1 << 16);
82-
if (r->shareable) rasr |= (1 << 18);
83-
84-
*((volatile uint32_t *)0xE000ED9C) = rbar;
85-
*((volatile uint32_t *)0xE000EDA0) = rasr;
86-
}
87-
88-
/* MPU->CTRL enable with PRIVDEFENA */
89-
*((volatile uint32_t *)0xE000ED94) = 5;
90-
91-
#elif defined(__ARM_ARCH_7R__)
92-
/* ---- Cortex-R5 PMSAv7 MPU via CP15 ---- */
93-
94-
/* Disable MPU: clear bit 0 of SCTLR (CP15 c1, c0, 0) */
95-
uint32_t sctlr;
96-
__asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(sctlr));
97-
sctlr &= ~1u;
98-
__asm volatile ("mcr p15, 0, %0, c1, c0, 0" :: "r"(sctlr));
99-
__asm volatile ("isb");
100-
101-
for (int i = 0; i < ctx->count; i++) {
102-
const eos_mpu_region_t *r = &ctx->regions[i];
103-
if (!r->enabled) continue;
104-
105-
/* Select region (RGNR — CP15 c6, c2, 0) */
106-
uint32_t rgnr = (uint32_t)i;
107-
__asm volatile ("mcr p15, 0, %0, c6, c2, 0" :: "r"(rgnr));
108-
109-
/* Calculate region size encoding (log2 - 1) */
110-
uint32_t size_bits = 0;
111-
uint32_t sz = r->size;
112-
while (sz > 1) { sz >>= 1; size_bits++; }
113-
114-
/* DRBAR — Region Base Address Register (CP15 c6, c1, 0) */
115-
__asm volatile ("mcr p15, 0, %0, c6, c1, 0" :: "r"(r->base_addr));
116-
117-
/* DRSR — Region Size and Enable Register (CP15 c6, c1, 2) */
118-
uint32_t drsr = (size_bits << 1) | 1; /* size + enable */
119-
__asm volatile ("mcr p15, 0, %0, c6, c1, 2" :: "r"(drsr));
120-
121-
/* DRACR — Region Access Control Register (CP15 c6, c1, 4) */
122-
uint32_t dracr = (r->access << 8);
123-
if (!r->executable) dracr |= (1 << 12); /* XN bit */
124-
if (r->cacheable) dracr |= (1 << 1); /* C bit */
125-
if (r->bufferable) dracr |= (1 << 0); /* B bit */
126-
if (r->shareable) dracr |= (1 << 2); /* S bit */
127-
__asm volatile ("mcr p15, 0, %0, c6, c1, 4" :: "r"(dracr));
128-
}
129-
130-
/* Enable MPU + background region (SCTLR bits 0 and 17) */
131-
__asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(sctlr));
132-
sctlr |= (1 << 0) | (1 << 17); /* M + BR */
133-
__asm volatile ("mcr p15, 0, %0, c1, c0, 0" :: "r"(sctlr));
134-
__asm volatile ("isb");
135-
136-
#endif
137-
138-
return 0;
139-
}
140-
141-
int eos_mpu_disable(void)
142-
{
143-
#if defined(__ARM_ARCH) && (__ARM_ARCH <= 7) && !defined(__aarch64__) && !defined(__ARM_ARCH_7R__)
144-
*((volatile uint32_t *)0xE000ED94) = 0;
145-
#elif defined(__ARM_ARCH_7R__)
146-
uint32_t sctlr;
147-
__asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(sctlr));
148-
sctlr &= ~1u;
149-
__asm volatile ("mcr p15, 0, %0, c1, c0, 0" :: "r"(sctlr));
150-
__asm volatile ("isb");
151-
#endif
152-
return 0;
153-
}
154-
155-
void eos_mpu_dump(const eos_mpu_ctx_t *ctx)
156-
{
157-
const char *access_str[] = {"NONE","P_RW","--","FULL_RW","--","P_RO","FULL_RO"};
158-
printf("MPU: %d regions (HW supports %d)\n", ctx->count, ctx->hw_regions);
159-
for (int i = 0; i < ctx->count; i++) {
160-
const eos_mpu_region_t *r = &ctx->regions[i];
161-
printf(" [%d] 0x%08x +0x%x %s %s%s%s\n",
162-
i, r->base_addr, r->size,
163-
access_str[r->access],
164-
r->executable ? "X" : "-",
165-
r->cacheable ? "C" : "-",
166-
r->enabled ? "" : " (disabled)");
167-
}
168-
}
1+
/**
2+
* @file mpu_boot.c
3+
* @brief MPU configuration during boot
4+
*/
5+
6+
#include "eos_mpu_boot.h"
7+
#include <string.h>
8+
#ifdef EBOOT_ENABLE_PRINTF
9+
#include <stdio.h>
10+
#endif
11+
12+
int eos_mpu_init(eos_mpu_ctx_t *ctx)
13+
{
14+
if (!ctx) return -1;
15+
memset(ctx, 0, sizeof(*ctx));
16+
ctx->hw_regions = 8; /* Default for Cortex-M4/M7 */
17+
return 0;
18+
}
19+
20+
int eos_mpu_add_region(eos_mpu_ctx_t *ctx, uint32_t base, uint32_t size,
21+
eos_mpu_access_t access, bool exec, bool cache)
22+
{
23+
if (!ctx || ctx->count >= EOS_MPU_MAX_REGIONS) return -1;
24+
if (ctx->count >= ctx->hw_regions) return -1;
25+
26+
eos_mpu_region_t *r = &ctx->regions[ctx->count++];
27+
r->base_addr = base;
28+
r->size = size;
29+
r->access = access;
30+
r->executable = exec;
31+
r->cacheable = cache;
32+
r->bufferable = cache;
33+
r->shareable = false;
34+
r->enabled = true;
35+
return 0;
36+
}
37+
38+
int eos_mpu_set_default(eos_mpu_ctx_t *ctx)
39+
{
40+
if (!ctx) return -1;
41+
ctx->count = 0;
42+
43+
/* Flash — read + execute, cacheable */
44+
eos_mpu_add_region(ctx, 0x08000000, 0x200000, EOS_MPU_FULL_RO, true, true);
45+
/* RAM — read + write, no execute, cacheable */
46+
eos_mpu_add_region(ctx, 0x20000000, 0x100000, EOS_MPU_FULL_RW, false, true);
47+
/* Peripherals — read + write, no execute, no cache */
48+
eos_mpu_add_region(ctx, 0x40000000, 0x20000000, EOS_MPU_FULL_RW, false, false);
49+
/* System — privileged only */
50+
eos_mpu_add_region(ctx, 0xE0000000, 0x10000, EOS_MPU_PRIV_RW, false, false);
51+
52+
return 0;
53+
}
54+
55+
int eos_mpu_apply(const eos_mpu_ctx_t *ctx)
56+
{
57+
if (!ctx) return -1;
58+
59+
/* ARM Cortex-M MPU programming:
60+
* 1. Disable MPU
61+
* 2. Program each region (RBAR + RASR registers)
62+
* 3. Enable MPU with PRIVDEFENA
63+
*
64+
* Actual register writes are platform-specific. */
65+
66+
#if defined(__ARM_ARCH) && (__ARM_ARCH <= 7) && !defined(__aarch64__)
67+
/* MPU->CTRL disable */
68+
*((volatile uint32_t *)0xE000ED94) = 0;
69+
70+
for (int i = 0; i < ctx->count; i++) {
71+
const eos_mpu_region_t *r = &ctx->regions[i];
72+
if (!r->enabled) continue;
73+
74+
/* Calculate region size encoding (log2 - 1) */
75+
uint32_t size_bits = 0;
76+
uint32_t sz = r->size;
77+
while (sz > 1) { sz >>= 1; size_bits++; }
78+
79+
uint32_t rbar = r->base_addr | (1 << 4) | i;
80+
uint32_t rasr = (r->access << 24) | (size_bits << 1) | 1;
81+
if (!r->executable) rasr |= (1 << 28);
82+
if (r->cacheable) rasr |= (1 << 17);
83+
if (r->bufferable) rasr |= (1 << 16);
84+
if (r->shareable) rasr |= (1 << 18);
85+
86+
*((volatile uint32_t *)0xE000ED9C) = rbar;
87+
*((volatile uint32_t *)0xE000EDA0) = rasr;
88+
}
89+
90+
/* MPU->CTRL enable with PRIVDEFENA */
91+
*((volatile uint32_t *)0xE000ED94) = 5;
92+
93+
#elif defined(__ARM_ARCH_7R__)
94+
/* ---- Cortex-R5 PMSAv7 MPU via CP15 ---- */
95+
96+
/* Disable MPU: clear bit 0 of SCTLR (CP15 c1, c0, 0) */
97+
uint32_t sctlr;
98+
__asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(sctlr));
99+
sctlr &= ~1u;
100+
__asm volatile ("mcr p15, 0, %0, c1, c0, 0" :: "r"(sctlr));
101+
__asm volatile ("isb");
102+
103+
for (int i = 0; i < ctx->count; i++) {
104+
const eos_mpu_region_t *r = &ctx->regions[i];
105+
if (!r->enabled) continue;
106+
107+
/* Select region (RGNR — CP15 c6, c2, 0) */
108+
uint32_t rgnr = (uint32_t)i;
109+
__asm volatile ("mcr p15, 0, %0, c6, c2, 0" :: "r"(rgnr));
110+
111+
/* Calculate region size encoding (log2 - 1) */
112+
uint32_t size_bits = 0;
113+
uint32_t sz = r->size;
114+
while (sz > 1) { sz >>= 1; size_bits++; }
115+
116+
/* DRBAR — Region Base Address Register (CP15 c6, c1, 0) */
117+
__asm volatile ("mcr p15, 0, %0, c6, c1, 0" :: "r"(r->base_addr));
118+
119+
/* DRSR — Region Size and Enable Register (CP15 c6, c1, 2) */
120+
uint32_t drsr = (size_bits << 1) | 1; /* size + enable */
121+
__asm volatile ("mcr p15, 0, %0, c6, c1, 2" :: "r"(drsr));
122+
123+
/* DRACR — Region Access Control Register (CP15 c6, c1, 4) */
124+
uint32_t dracr = (r->access << 8);
125+
if (!r->executable) dracr |= (1 << 12); /* XN bit */
126+
if (r->cacheable) dracr |= (1 << 1); /* C bit */
127+
if (r->bufferable) dracr |= (1 << 0); /* B bit */
128+
if (r->shareable) dracr |= (1 << 2); /* S bit */
129+
__asm volatile ("mcr p15, 0, %0, c6, c1, 4" :: "r"(dracr));
130+
}
131+
132+
/* Enable MPU + background region (SCTLR bits 0 and 17) */
133+
__asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(sctlr));
134+
sctlr |= (1 << 0) | (1 << 17); /* M + BR */
135+
__asm volatile ("mcr p15, 0, %0, c1, c0, 0" :: "r"(sctlr));
136+
__asm volatile ("isb");
137+
138+
#endif
139+
140+
return 0;
141+
}
142+
143+
int eos_mpu_disable(void)
144+
{
145+
#if defined(__ARM_ARCH) && (__ARM_ARCH <= 7) && !defined(__aarch64__) && !defined(__ARM_ARCH_7R__)
146+
*((volatile uint32_t *)0xE000ED94) = 0;
147+
#elif defined(__ARM_ARCH_7R__)
148+
uint32_t sctlr;
149+
__asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(sctlr));
150+
sctlr &= ~1u;
151+
__asm volatile ("mcr p15, 0, %0, c1, c0, 0" :: "r"(sctlr));
152+
__asm volatile ("isb");
153+
#endif
154+
return 0;
155+
}
156+
157+
void eos_mpu_dump(const eos_mpu_ctx_t *ctx)
158+
{
159+
#ifdef EBOOT_ENABLE_PRINTF
160+
const char *access_str[] = {"NONE","P_RW","--","FULL_RW","--","P_RO","FULL_RO"};
161+
printf("MPU: %d regions (HW supports %d)\n", ctx->count, ctx->hw_regions);
162+
for (int i = 0; i < ctx->count; i++) {
163+
const eos_mpu_region_t *r = &ctx->regions[i];
164+
printf(" [%d] 0x%08x +0x%x %s %s%s%s\n",
165+
i, r->base_addr, r->size,
166+
access_str[r->access],
167+
r->executable ? "X" : "-",
168+
r->cacheable ? "C" : "-",
169+
r->enabled ? "" : " (disabled)");
170+
}
171+
#else
172+
(void)ctx;
173+
#endif
174+
}
175+
r->enabled ? "" : " (disabled)");
176+
}
177+
#else
178+
(void)ctx;
179+
#endif
180+
}

0 commit comments

Comments
 (0)