Browse Source

Added TrustZone interactive example (#38)

Added trustzone project
pull/43/head
Felipe Torrezan 7 months ago
committed by GitHub
parent
commit
8bbfc286dd
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 10
      examples/trustzone/CMakeLists.txt
  2. 20
      examples/trustzone/non-secure/CMakeLists.txt
  3. 55
      examples/trustzone/non-secure/non-secure-hello.c
  4. 23
      examples/trustzone/non-secure/v2m-mps2_ns.icf
  5. 23
      examples/trustzone/secure/CMakeLists.txt
  6. 156
      examples/trustzone/secure/secure-hello.c
  7. 35
      examples/trustzone/secure/secure-hello.h
  8. 27
      examples/trustzone/secure/v2m-mps2_s.icf

10
examples/trustzone/CMakeLists.txt

@ -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()

20
examples/trustzone/non-secure/CMakeLists.txt

@ -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
)

55
examples/trustzone/non-secure/non-secure-hello.c

@ -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()` */
};

23
examples/trustzone/non-secure/v2m-mps2_ns.icf

@ -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 };

23
examples/trustzone/secure/CMakeLists.txt

@ -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
)

156
examples/trustzone/secure/secure-hello.c

@ -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;
}

35
examples/trustzone/secure/secure-hello.h

@ -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);

27
examples/trustzone/secure/v2m-mps2_s.icf

@ -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…
Cancel
Save