Felipe Torrezan
7 months ago
committed by
GitHub
8 changed files with 349 additions and 0 deletions
@ -0,0 +1,10 @@ |
|||
cmake_minimum_required(VERSION 3.20) |
|||
|
|||
project(TrustZone LANGUAGES C) |
|||
|
|||
add_subdirectory(secure) |
|||
add_subdirectory(non-secure) |
|||
|
|||
# TODO 1: Add `secure` as a dependency for `non-secure` |
|||
add_dependencies() |
|||
|
@ -0,0 +1,20 @@ |
|||
add_executable(non-secure) |
|||
|
|||
target_sources(non-secure PRIVATE non-secure-hello.c) |
|||
|
|||
target_compile_options(non-secure PRIVATE |
|||
--cpu=$<TARGET_PROPERTY:secure,CPU> |
|||
--no_wrap_diagnostics |
|||
) |
|||
|
|||
target_include_directories(non-secure PRIVATE |
|||
# TODO 4: Make use of the `secure` include directories |
|||
) |
|||
|
|||
target_link_options(non-secure PRIVATE |
|||
--cpu=$<TARGET_PROPERTY:secure,CPU> |
|||
--config ${CMAKE_CURRENT_SOURCE_DIR}/v2m-mps2_ns.icf |
|||
--semihosting |
|||
# TODO 5: Link agains the import library generated from the `secure` target |
|||
# TODO 6: Specify "no entry point" for the `non-secure` target |
|||
) |
@ -0,0 +1,55 @@ |
|||
/*
|
|||
Copyright (c) 2018-2024, IAR Systems AB. |
|||
|
|||
`non-secure` "Hello" - A simple CMSE example |
|||
This example is not production-ready within CMSE best-practices. |
|||
However, it showcases some features within CMSE usage contexts. |
|||
*/ |
|||
|
|||
#if (__ARM_FEATURE_CMSE & 1) == 0 |
|||
#error "Need ARMv8-M security extensions" |
|||
#elif (__ARM_FEATURE_CMSE & 2) != 0 |
|||
#error "Compile without --cmse" |
|||
#endif |
|||
|
|||
#include <arm_cmse.h> |
|||
#include "secure-hello.h" |
|||
|
|||
#pragma section="CSTACK" |
|||
|
|||
void main_ns(void); |
|||
|
|||
/* C Runtime initialization function for DATA and BSS regions */ |
|||
void __iar_data_init3(void); |
|||
|
|||
/* Override the default C Runtime startup code */ |
|||
void __iar_program_start() {} |
|||
|
|||
static char * bye(void) |
|||
{ |
|||
return "Goodbye, for now."; |
|||
} |
|||
|
|||
/* main_ns() is the entry for the `non-secure` target.
|
|||
Note: called main_ns to not confuse debugger with multiple main() |
|||
*/ |
|||
void main_ns(void) |
|||
{ |
|||
/* Register bye to be called at system termination */ |
|||
register_secure_goodbye(bye); |
|||
|
|||
/* Let the world know non-secure code is up and running */ |
|||
secure_hello("from non-secure World"); |
|||
|
|||
/* Nothing more to do at this point... */ |
|||
} |
|||
|
|||
/* Inteface towards the secure part */ |
|||
#pragma location=NON_SECURE_ENTRY_TABLE |
|||
__root const non_secure_init_t init_table = |
|||
{ |
|||
__iar_data_init3, /* initialization function */ |
|||
__section_end("CSTACK"), /* non-secure stack */ |
|||
main_ns /* non-secure `main()` */ |
|||
}; |
|||
|
@ -0,0 +1,23 @@ |
|||
|
|||
/***************************************************************************** |
|||
* |
|||
* Memory setup for the `non-secure` target |
|||
* |
|||
* In this example non-secure state may use |
|||
* 0x200000-0x1FFFFF and 0x201FFFFF-0x203FFFFF. |
|||
* |
|||
*****************************************************************************/ |
|||
|
|||
define memory mem with size = 4G; |
|||
define region ROM_NS_region = mem:[from 0x00200000 to 0x003FFFFF]; |
|||
define region RAM_NS_region = mem:[from 0x20200000 to 0x203FFFFF]; |
|||
|
|||
define block CSTACK with alignment = 8, size = 0x1000 { }; |
|||
define block HEAP with alignment = 8, size = 0x1000 { }; |
|||
|
|||
do not initialize { section .noinit }; |
|||
|
|||
initialize by copy { rw }; |
|||
|
|||
place in ROM_NS_region { readonly }; |
|||
place in RAM_NS_region { readwrite, block CSTACK, block HEAP }; |
@ -0,0 +1,23 @@ |
|||
add_executable(secure) |
|||
|
|||
target_sources(secure PRIVATE secure-hello.c) |
|||
|
|||
set_target_properties(secure PROPERTIES |
|||
CPU cortex-m33 |
|||
) |
|||
|
|||
target_compile_options(secure PRIVATE |
|||
--cpu=$<TARGET_PROPERTY:CPU> |
|||
# TODO 2: Enable the CMSE in the compiler flags |
|||
) |
|||
|
|||
target_include_directories(secure PUBLIC |
|||
${CMAKE_CURRENT_SOURCE_DIR} |
|||
) |
|||
|
|||
target_link_options(secure PRIVATE |
|||
--semihosting |
|||
--cpu=$<TARGET_PROPERTY:CPU> |
|||
--config ${CMAKE_CURRENT_SOURCE_DIR}/v2m-mps2_s.icf |
|||
# TODO 3: Set the linker to produce an import library, consumed by the `non-secure` target |
|||
) |
@ -0,0 +1,156 @@ |
|||
|
|||
/*
|
|||
Copyright (c) 2018-2024, IAR Systems AB. |
|||
|
|||
`secure` "Hello" - A simple CMSE example |
|||
This minimalistic example is not production-ready within CMSE best-practices. |
|||
However, it showcases some features within CMSE usage contexts. |
|||
|
|||
The gateway interface towards the `non-secure` target consists of 2 functions |
|||
- secure_hello(char const *str) |
|||
Validates str and prints str to standard out |
|||
|
|||
- register_secure_goodbye(secure_goodbye_t fptr) |
|||
Validates fptr and stores it to be used when system terminates |
|||
|
|||
Expects the `non-secure` target to have a |
|||
`non_secure_init_t` structure @ 0x0020_0000. |
|||
*/ |
|||
|
|||
#if (__ARM_FEATURE_CMSE & 1) == 0 |
|||
#error "Need ARMv8-M security extensions" |
|||
#elif (__ARM_FEATURE_CMSE & 2) == 0 |
|||
#error "Compile with --cmse" |
|||
#endif |
|||
|
|||
#include <arm_cmse.h> |
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
#include "secure-hello.h" |
|||
|
|||
#pragma language=extended |
|||
|
|||
/* Check address of string provided by `non-secure` */ |
|||
static void check_string(char * s); |
|||
|
|||
/* Setup of access rights for memory regions */ |
|||
static void SAU_setup(void); |
|||
|
|||
/* Callback, on exit from `secure` */ |
|||
static secure_goodbye_t cb_goodbye = NULL; |
|||
|
|||
/* First entry: secure_hello */ |
|||
__cmse_nonsecure_entry void secure_hello(char * s) |
|||
{ |
|||
/* Validate string if caller is non-secure */ |
|||
if (cmse_nonsecure_caller()) |
|||
check_string(s); |
|||
|
|||
printf("Hello %s!\n", s); |
|||
} |
|||
|
|||
/* Second entry: register_secure_goodbye */ |
|||
__cmse_nonsecure_entry void register_secure_goodbye(secure_goodbye_t goodbye) |
|||
{ |
|||
if (goodbye) |
|||
{ |
|||
/* If goodbye is not NULL make sure the address
|
|||
* can be read from non-secure state |
|||
*/ |
|||
cmse_address_info_t r = cmse_TTA_fptr(goodbye); |
|||
if (!r.flags.nonsecure_read_ok) |
|||
{ |
|||
printf("Unacceptable function pointer!\n"); |
|||
abort(); |
|||
} |
|||
} |
|||
cb_goodbye = goodbye; |
|||
} |
|||
|
|||
/* "Handle" to the non-secure image */ |
|||
#define unsecure_table (*((non_secure_init_t const *)NON_SECURE_ENTRY_TABLE)) |
|||
|
|||
int main(void) |
|||
{ |
|||
/* Setup non-secure and non-secure callable regions */ |
|||
SAU_setup(); |
|||
|
|||
/* Let the world know non-secure code is up and running */ |
|||
secure_hello("from secure World"); |
|||
|
|||
/* Set stack pointer for the `non-secure` target */ |
|||
asm volatile("MSR SP_NS, %0" :: "r" (unsecure_table.stack)); |
|||
|
|||
/* Let non-secure code initialize its environment */ |
|||
unsecure_table.init(); |
|||
|
|||
/* Call non-secure main */ |
|||
unsecure_table.main(); |
|||
|
|||
/* Nothing more to do in this system... */ |
|||
|
|||
/* Goodbye... */ |
|||
if (cb_goodbye != NULL) |
|||
{ |
|||
char * s = cb_goodbye(); |
|||
check_string(s); |
|||
printf("%s\n", s); |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
#define MAX_STRING_LENGTH 42 |
|||
void check_string(char * s) |
|||
{ |
|||
/* Do not allow arbitrary length of string */ |
|||
size_t n = strnlen(s, MAX_STRING_LENGTH); |
|||
if (n == MAX_STRING_LENGTH && s[n] != '\0') |
|||
{ |
|||
printf("Unacceptable string length!\n"); |
|||
abort(); |
|||
} |
|||
if (cmse_check_address_range(s, n, CMSE_MPU_UNPRIV | CMSE_MPU_READ) == NULL) |
|||
{ |
|||
printf("Unacceptable address range!\n"); |
|||
abort(); |
|||
} |
|||
} |
|||
|
|||
/* When writing this we have no header file for the secure region SFRs,
|
|||
* so for now we define them here where they are needed. |
|||
*/ |
|||
#define SAU_CTRL (*((volatile unsigned int *) 0xE000EDD0)) |
|||
#define SAU_RNR (*((volatile unsigned int *) 0xE000EDD8)) |
|||
#define SAU_RBAR (*((volatile unsigned int *) 0xE000EDDC)) |
|||
#define SAU_RLAR (*((volatile unsigned int *) 0xE000EDE0)) |
|||
|
|||
/*
|
|||
* Note: MPU protection is not setup in this example |
|||
*/ |
|||
|
|||
static void SAU_setup(void) |
|||
{ |
|||
/* region #0: non-secure callable, 0x000000C0 - 0x000000DF */ |
|||
SAU_RNR = 0; |
|||
SAU_RBAR = 0x000000C0; |
|||
SAU_RLAR = 0x000000C3; |
|||
|
|||
/* region #1: non-secure, 0x00200000 - 0x003fffff */ |
|||
SAU_RNR = 1; |
|||
SAU_RBAR = 0x00200000; |
|||
SAU_RLAR = 0x003fffe1; |
|||
|
|||
/* region #2: non-secure, 0x20200000 - 0x203fffff */ |
|||
SAU_RNR = 2; |
|||
SAU_RBAR = 0x20200000; |
|||
SAU_RLAR = 0x203fffe1; |
|||
|
|||
/* region #3: non-secure, 0x40000000 - 0x4004001f */ |
|||
SAU_RNR = 3; |
|||
SAU_RBAR = 0x40000000; |
|||
SAU_RLAR = 0x40040001; |
|||
|
|||
/* Enable SAU */ |
|||
SAU_CTRL = 1; |
|||
} |
@ -0,0 +1,35 @@ |
|||
/*
|
|||
Copyright (c) 2018-2024, IAR Systems AB. |
|||
|
|||
Header file for the `trustzone` example. |
|||
Contains definitions used in the following targets: |
|||
- `secure` |
|||
- `non-secure` |
|||
*/ |
|||
|
|||
#pragma once |
|||
#pragma language = extended |
|||
|
|||
#if (__ARM_FEATURE_CMSE == 3U) |
|||
#define CMSE_NS_CALL __cmse_nonsecure_call |
|||
#define CMSE_NS_ENTRY __cmse_nonsecure_entry |
|||
#else |
|||
#define CMSE_NS_CALL |
|||
#define CMSE_NS_ENTRY |
|||
#endif |
|||
|
|||
#define NON_SECURE_ENTRY_TABLE 0x00200000 |
|||
|
|||
typedef CMSE_NS_CALL char * (*secure_goodbye_t)(void); |
|||
|
|||
typedef void (CMSE_NS_CALL *ns_func0)(void); |
|||
|
|||
typedef struct non_secure_init_t |
|||
{ |
|||
ns_func0 init; |
|||
void* stack; |
|||
ns_func0 main; |
|||
} non_secure_init_t; |
|||
|
|||
CMSE_NS_ENTRY void secure_hello(char * s); |
|||
CMSE_NS_ENTRY void register_secure_goodbye(secure_goodbye_t goodbye); |
@ -0,0 +1,27 @@ |
|||
|
|||
/***************************************************************************** |
|||
* Memory setup for the `secure` target |
|||
* |
|||
* In this example secure state may use 0-0x1FFFFF and 0x20000000-0x201FFFFF |
|||
* The NSC_region is the region that can be called from non-secure code, |
|||
* it is populated by the linker with veneers to function that has been |
|||
* declared with __cmse_nonsecure_entry. |
|||
* |
|||
*****************************************************************************/ |
|||
|
|||
define memory mem with size = 4G; |
|||
define region NSC_region = mem:[from 0x000000C0 to 0x000000DF]; |
|||
define region ROM_S_region = mem:[from 0x000000E0 to 0x001FFFFF]; |
|||
define region RAM_S_region = mem:[from 0x20000000 to 0x201FFFFF]; |
|||
|
|||
define block CSTACK with alignment = 8, size = 0x1000 { }; |
|||
define block HEAP with alignment = 8, size = 0x1000 { }; |
|||
|
|||
do not initialize { section .noinit }; |
|||
|
|||
initialize by copy { rw }; |
|||
|
|||
place at address mem:0 { section .intvec }; |
|||
place in NSC_region { section Veneer$$CMSE }; |
|||
place in ROM_S_region { readonly }; |
|||
place in RAM_S_region { readwrite, zi, block CSTACK, block HEAP }; |
Loading…
Reference in new issue