Skip to content

Commit 8bbfc28

Browse files
author
Felipe Torrezan
authored
Added TrustZone interactive example (#38)
Added trustzone project
1 parent 09c4d83 commit 8bbfc28

File tree

8 files changed

+349
-0
lines changed

8 files changed

+349
-0
lines changed

examples/trustzone/CMakeLists.txt

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
cmake_minimum_required(VERSION 3.20)
2+
3+
project(TrustZone LANGUAGES C)
4+
5+
add_subdirectory(secure)
6+
add_subdirectory(non-secure)
7+
8+
# TODO 1: Add `secure` as a dependency for `non-secure`
9+
add_dependencies()
10+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
add_executable(non-secure)
2+
3+
target_sources(non-secure PRIVATE non-secure-hello.c)
4+
5+
target_compile_options(non-secure PRIVATE
6+
--cpu=$<TARGET_PROPERTY:secure,CPU>
7+
--no_wrap_diagnostics
8+
)
9+
10+
target_include_directories(non-secure PRIVATE
11+
# TODO 4: Make use of the `secure` include directories
12+
)
13+
14+
target_link_options(non-secure PRIVATE
15+
--cpu=$<TARGET_PROPERTY:secure,CPU>
16+
--config ${CMAKE_CURRENT_SOURCE_DIR}/v2m-mps2_ns.icf
17+
--semihosting
18+
# TODO 5: Link agains the import library generated from the `secure` target
19+
# TODO 6: Specify "no entry point" for the `non-secure` target
20+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
Copyright (c) 2018-2024, IAR Systems AB.
3+
4+
`non-secure` "Hello" - A simple CMSE example
5+
This example is not production-ready within CMSE best-practices.
6+
However, it showcases some features within CMSE usage contexts.
7+
*/
8+
9+
#if (__ARM_FEATURE_CMSE & 1) == 0
10+
#error "Need ARMv8-M security extensions"
11+
#elif (__ARM_FEATURE_CMSE & 2) != 0
12+
#error "Compile without --cmse"
13+
#endif
14+
15+
#include <arm_cmse.h>
16+
#include "secure-hello.h"
17+
18+
#pragma section="CSTACK"
19+
20+
void main_ns(void);
21+
22+
/* C Runtime initialization function for DATA and BSS regions */
23+
void __iar_data_init3(void);
24+
25+
/* Override the default C Runtime startup code */
26+
void __iar_program_start() {}
27+
28+
static char * bye(void)
29+
{
30+
return "Goodbye, for now.";
31+
}
32+
33+
/* main_ns() is the entry for the `non-secure` target.
34+
Note: called main_ns to not confuse debugger with multiple main()
35+
*/
36+
void main_ns(void)
37+
{
38+
/* Register bye to be called at system termination */
39+
register_secure_goodbye(bye);
40+
41+
/* Let the world know non-secure code is up and running */
42+
secure_hello("from non-secure World");
43+
44+
/* Nothing more to do at this point... */
45+
}
46+
47+
/* Inteface towards the secure part */
48+
#pragma location=NON_SECURE_ENTRY_TABLE
49+
__root const non_secure_init_t init_table =
50+
{
51+
__iar_data_init3, /* initialization function */
52+
__section_end("CSTACK"), /* non-secure stack */
53+
main_ns /* non-secure `main()` */
54+
};
55+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
2+
/*****************************************************************************
3+
*
4+
* Memory setup for the `non-secure` target
5+
*
6+
* In this example non-secure state may use
7+
* 0x200000-0x1FFFFF and 0x201FFFFF-0x203FFFFF.
8+
*
9+
*****************************************************************************/
10+
11+
define memory mem with size = 4G;
12+
define region ROM_NS_region = mem:[from 0x00200000 to 0x003FFFFF];
13+
define region RAM_NS_region = mem:[from 0x20200000 to 0x203FFFFF];
14+
15+
define block CSTACK with alignment = 8, size = 0x1000 { };
16+
define block HEAP with alignment = 8, size = 0x1000 { };
17+
18+
do not initialize { section .noinit };
19+
20+
initialize by copy { rw };
21+
22+
place in ROM_NS_region { readonly };
23+
place in RAM_NS_region { readwrite, block CSTACK, block HEAP };
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
add_executable(secure)
2+
3+
target_sources(secure PRIVATE secure-hello.c)
4+
5+
set_target_properties(secure PROPERTIES
6+
CPU cortex-m33
7+
)
8+
9+
target_compile_options(secure PRIVATE
10+
--cpu=$<TARGET_PROPERTY:CPU>
11+
# TODO 2: Enable the CMSE in the compiler flags
12+
)
13+
14+
target_include_directories(secure PUBLIC
15+
${CMAKE_CURRENT_SOURCE_DIR}
16+
)
17+
18+
target_link_options(secure PRIVATE
19+
--semihosting
20+
--cpu=$<TARGET_PROPERTY:CPU>
21+
--config ${CMAKE_CURRENT_SOURCE_DIR}/v2m-mps2_s.icf
22+
# TODO 3: Set the linker to produce an import library, consumed by the `non-secure` target
23+
)
+156
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
2+
/*
3+
Copyright (c) 2018-2024, IAR Systems AB.
4+
5+
`secure` "Hello" - A simple CMSE example
6+
This minimalistic example is not production-ready within CMSE best-practices.
7+
However, it showcases some features within CMSE usage contexts.
8+
9+
The gateway interface towards the `non-secure` target consists of 2 functions
10+
- secure_hello(char const *str)
11+
Validates str and prints str to standard out
12+
13+
- register_secure_goodbye(secure_goodbye_t fptr)
14+
Validates fptr and stores it to be used when system terminates
15+
16+
Expects the `non-secure` target to have a
17+
`non_secure_init_t` structure @ 0x0020_0000.
18+
*/
19+
20+
#if (__ARM_FEATURE_CMSE & 1) == 0
21+
#error "Need ARMv8-M security extensions"
22+
#elif (__ARM_FEATURE_CMSE & 2) == 0
23+
#error "Compile with --cmse"
24+
#endif
25+
26+
#include <arm_cmse.h>
27+
#include <stdio.h>
28+
#include <stdlib.h>
29+
#include <string.h>
30+
#include "secure-hello.h"
31+
32+
#pragma language=extended
33+
34+
/* Check address of string provided by `non-secure` */
35+
static void check_string(char * s);
36+
37+
/* Setup of access rights for memory regions */
38+
static void SAU_setup(void);
39+
40+
/* Callback, on exit from `secure` */
41+
static secure_goodbye_t cb_goodbye = NULL;
42+
43+
/* First entry: secure_hello */
44+
__cmse_nonsecure_entry void secure_hello(char * s)
45+
{
46+
/* Validate string if caller is non-secure */
47+
if (cmse_nonsecure_caller())
48+
check_string(s);
49+
50+
printf("Hello %s!\n", s);
51+
}
52+
53+
/* Second entry: register_secure_goodbye */
54+
__cmse_nonsecure_entry void register_secure_goodbye(secure_goodbye_t goodbye)
55+
{
56+
if (goodbye)
57+
{
58+
/* If goodbye is not NULL make sure the address
59+
* can be read from non-secure state
60+
*/
61+
cmse_address_info_t r = cmse_TTA_fptr(goodbye);
62+
if (!r.flags.nonsecure_read_ok)
63+
{
64+
printf("Unacceptable function pointer!\n");
65+
abort();
66+
}
67+
}
68+
cb_goodbye = goodbye;
69+
}
70+
71+
/* "Handle" to the non-secure image */
72+
#define unsecure_table (*((non_secure_init_t const *)NON_SECURE_ENTRY_TABLE))
73+
74+
int main(void)
75+
{
76+
/* Setup non-secure and non-secure callable regions */
77+
SAU_setup();
78+
79+
/* Let the world know non-secure code is up and running */
80+
secure_hello("from secure World");
81+
82+
/* Set stack pointer for the `non-secure` target */
83+
asm volatile("MSR SP_NS, %0" :: "r" (unsecure_table.stack));
84+
85+
/* Let non-secure code initialize its environment */
86+
unsecure_table.init();
87+
88+
/* Call non-secure main */
89+
unsecure_table.main();
90+
91+
/* Nothing more to do in this system... */
92+
93+
/* Goodbye... */
94+
if (cb_goodbye != NULL)
95+
{
96+
char * s = cb_goodbye();
97+
check_string(s);
98+
printf("%s\n", s);
99+
}
100+
return 0;
101+
}
102+
103+
#define MAX_STRING_LENGTH 42
104+
void check_string(char * s)
105+
{
106+
/* Do not allow arbitrary length of string */
107+
size_t n = strnlen(s, MAX_STRING_LENGTH);
108+
if (n == MAX_STRING_LENGTH && s[n] != '\0')
109+
{
110+
printf("Unacceptable string length!\n");
111+
abort();
112+
}
113+
if (cmse_check_address_range(s, n, CMSE_MPU_UNPRIV | CMSE_MPU_READ) == NULL)
114+
{
115+
printf("Unacceptable address range!\n");
116+
abort();
117+
}
118+
}
119+
120+
/* When writing this we have no header file for the secure region SFRs,
121+
* so for now we define them here where they are needed.
122+
*/
123+
#define SAU_CTRL (*((volatile unsigned int *) 0xE000EDD0))
124+
#define SAU_RNR (*((volatile unsigned int *) 0xE000EDD8))
125+
#define SAU_RBAR (*((volatile unsigned int *) 0xE000EDDC))
126+
#define SAU_RLAR (*((volatile unsigned int *) 0xE000EDE0))
127+
128+
/*
129+
* Note: MPU protection is not setup in this example
130+
*/
131+
132+
static void SAU_setup(void)
133+
{
134+
/* region #0: non-secure callable, 0x000000C0 - 0x000000DF */
135+
SAU_RNR = 0;
136+
SAU_RBAR = 0x000000C0;
137+
SAU_RLAR = 0x000000C3;
138+
139+
/* region #1: non-secure, 0x00200000 - 0x003fffff */
140+
SAU_RNR = 1;
141+
SAU_RBAR = 0x00200000;
142+
SAU_RLAR = 0x003fffe1;
143+
144+
/* region #2: non-secure, 0x20200000 - 0x203fffff */
145+
SAU_RNR = 2;
146+
SAU_RBAR = 0x20200000;
147+
SAU_RLAR = 0x203fffe1;
148+
149+
/* region #3: non-secure, 0x40000000 - 0x4004001f */
150+
SAU_RNR = 3;
151+
SAU_RBAR = 0x40000000;
152+
SAU_RLAR = 0x40040001;
153+
154+
/* Enable SAU */
155+
SAU_CTRL = 1;
156+
}
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
Copyright (c) 2018-2024, IAR Systems AB.
3+
4+
Header file for the `trustzone` example.
5+
Contains definitions used in the following targets:
6+
- `secure`
7+
- `non-secure`
8+
*/
9+
10+
#pragma once
11+
#pragma language = extended
12+
13+
#if (__ARM_FEATURE_CMSE == 3U)
14+
#define CMSE_NS_CALL __cmse_nonsecure_call
15+
#define CMSE_NS_ENTRY __cmse_nonsecure_entry
16+
#else
17+
#define CMSE_NS_CALL
18+
#define CMSE_NS_ENTRY
19+
#endif
20+
21+
#define NON_SECURE_ENTRY_TABLE 0x00200000
22+
23+
typedef CMSE_NS_CALL char * (*secure_goodbye_t)(void);
24+
25+
typedef void (CMSE_NS_CALL *ns_func0)(void);
26+
27+
typedef struct non_secure_init_t
28+
{
29+
ns_func0 init;
30+
void* stack;
31+
ns_func0 main;
32+
} non_secure_init_t;
33+
34+
CMSE_NS_ENTRY void secure_hello(char * s);
35+
CMSE_NS_ENTRY void register_secure_goodbye(secure_goodbye_t goodbye);
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
2+
/*****************************************************************************
3+
* Memory setup for the `secure` target
4+
*
5+
* In this example secure state may use 0-0x1FFFFF and 0x20000000-0x201FFFFF
6+
* The NSC_region is the region that can be called from non-secure code,
7+
* it is populated by the linker with veneers to function that has been
8+
* declared with __cmse_nonsecure_entry.
9+
*
10+
*****************************************************************************/
11+
12+
define memory mem with size = 4G;
13+
define region NSC_region = mem:[from 0x000000C0 to 0x000000DF];
14+
define region ROM_S_region = mem:[from 0x000000E0 to 0x001FFFFF];
15+
define region RAM_S_region = mem:[from 0x20000000 to 0x201FFFFF];
16+
17+
define block CSTACK with alignment = 8, size = 0x1000 { };
18+
define block HEAP with alignment = 8, size = 0x1000 { };
19+
20+
do not initialize { section .noinit };
21+
22+
initialize by copy { rw };
23+
24+
place at address mem:0 { section .intvec };
25+
place in NSC_region { section Veneer$$CMSE };
26+
place in ROM_S_region { readonly };
27+
place in RAM_S_region { readwrite, zi, block CSTACK, block HEAP };

0 commit comments

Comments
 (0)