App: Example NS app

Contains an example implementation for NS application using Trusted
Firmware M interface.
This app is also used for triggering the test suites.

Change-Id: Ie294ab683014a70112d4aa78e415882ab0e872fa
Signed-off-by: Abhishek Pandit <abhishek.pandit@arm.com>
diff --git a/app/ext/tz_context.c b/app/ext/tz_context.c
new file mode 100644
index 0000000..26e8081
--- /dev/null
+++ b/app/ext/tz_context.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2015-2016 ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * $Date:        15. October 2016
+ * $Revision:    1.1.0
+ *
+ * Project:      TrustZone for ARMv8-M
+ * Title:        Context Management for ARMv8-M TrustZone - Stub implementation,
+ *               TFM will take charge of the stack memory management in S mode
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "tz_context.h"
+
+
+/// Initialize secure context memory system
+/// \return execution status (1: success, 0: error)
+uint32_t TZ_InitContextSystem_S (void) {
+  return 1U;    // Success
+}
+
+
+/// Allocate context memory for calling secure software modules in TrustZone
+/// \param[in]  module   identifies software modules called from non-secure mode
+/// \return value != 0 id TrustZone memory slot identifier
+/// \return value 0    no memory available or internal error
+TZ_MemoryId_t TZ_AllocModuleContext_S (TZ_ModuleId_t module) {
+  uint32_t slot = 0;
+  return (slot + 1U);
+}
+
+
+/// Free context memory that was previously allocated with \ref TZ_AllocModuleContext_S
+/// \param[in]  id  TrustZone memory slot identifier
+/// \return execution status (1: success, 0: error)
+uint32_t TZ_FreeModuleContext_S (TZ_MemoryId_t id) {
+  return 1U;    // Success
+}
+
+
+/// Load secure context (called on RTOS thread context switch)
+/// \param[in]  id  TrustZone memory slot identifier
+/// \return execution status (1: success, 0: error)
+uint32_t TZ_LoadContext_S (TZ_MemoryId_t id) {
+  return 1U;    // Success
+}
+
+
+/// Store secure context (called on RTOS thread context switch)
+/// \param[in]  id  TrustZone memory slot identifier
+/// \return execution status (1: success, 0: error)
+uint32_t TZ_StoreContext_S (TZ_MemoryId_t id) {
+  return 1U;    // Success
+}
diff --git a/app/ext/tz_context.h b/app/ext/tz_context.h
new file mode 100644
index 0000000..cd6d8ab
--- /dev/null
+++ b/app/ext/tz_context.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015-2016 ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * $Date:        21. September 2016
+ * $Revision:    V1.0
+ *
+ * Project:      TrustZone for ARMv8-M
+ * Title:        Context Management for ARMv8-M TrustZone
+ *
+ * Version 1.0
+ *    Initial Release
+ *---------------------------------------------------------------------------*/
+
+#ifndef TZ_CONTEXT_H
+#define TZ_CONTEXT_H
+
+#include <stdint.h>
+
+#ifndef TZ_MODULEID_T
+#define TZ_MODULEID_T
+/// \details Data type that identifies secure software modules called by a process.
+typedef uint32_t TZ_ModuleId_t;
+#endif
+
+/// \details TZ Memory ID identifies an allocated memory slot.
+typedef uint32_t TZ_MemoryId_t;
+
+/// Initialize secure context memory system
+/// \return execution status (1: success, 0: error)
+uint32_t TZ_InitContextSystem_S (void);
+
+/// Allocate context memory for calling secure software modules in TrustZone
+/// \param[in]  module   identifies software modules called from non-secure mode
+/// \return value != 0 id TrustZone memory slot identifier
+/// \return value 0    no memory available or internal error
+TZ_MemoryId_t TZ_AllocModuleContext_S (TZ_ModuleId_t module);
+
+/// Free context memory that was previously allocated with \ref TZ_AllocModuleContext_S
+/// \param[in]  id  TrustZone memory slot identifier
+/// \return execution status (1: success, 0: error)
+uint32_t TZ_FreeModuleContext_S (TZ_MemoryId_t id);
+
+/// Load secure context (called on RTOS thread context switch)
+/// \param[in]  id  TrustZone memory slot identifier
+/// \return execution status (1: success, 0: error)
+uint32_t TZ_LoadContext_S (TZ_MemoryId_t id);
+
+/// Store secure context (called on RTOS thread context switch)
+/// \param[in]  id  TrustZone memory slot identifier
+/// \return execution status (1: success, 0: error)
+uint32_t TZ_StoreContext_S (TZ_MemoryId_t id);
+
+#endif  // TZ_CONTEXT_H
diff --git a/app/main_ns.c b/app/main_ns.c
new file mode 100644
index 0000000..a0d64d5
--- /dev/null
+++ b/app/main_ns.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "cmsis.h"
+#include "tfm_api.h"
+#include "cmsis_os2.h"
+#include "tfm_integ_test.h"
+#include "tfm_ns_svc.h"
+#include "tfm_sst_svc_handler.h"
+#include "tfm_ns_lock.h"
+#ifdef CORE_TEST_SERVICES
+#include "test/suites/core/non_secure/svc_core_test_ns.h"
+#endif
+#ifdef TEST_FRAMEWORK_NS
+#include "test/framework/integ_test.h"
+#endif
+
+#include "Driver_USART.h"
+
+/* For UART the CMSIS driver is used */
+extern ARM_DRIVER_USART Driver_USART0;
+
+/**
+ * \brief Modified table template for user defined SVC functions
+ *
+ * \details RTX has a weak definition of osRtxUserSVC, which
+ *          is overridden here
+ */
+extern void * const osRtxUserSVC[1+USER_SVC_COUNT];
+       void * const osRtxUserSVC[1+USER_SVC_COUNT] = {
+  (void *)USER_SVC_COUNT,
+
+/* SERVICES_TEST_NS */
+  (void *)tfm_sst_svc_get_handle,
+  (void *)tfm_sst_svc_create,
+  (void *)tfm_sst_svc_get_attributes,
+  (void *)tfm_sst_svc_read,
+  (void *)tfm_sst_svc_write,
+  (void *)tfm_sst_svc_delete,
+
+#if defined(CORE_TEST_INTERACTIVE)
+  (void *)svc_secure_decrement_ns_lock_1,
+  (void *)svc_secure_decrement_ns_lock_2,
+#endif /* CORE_TEST_INTERACTIVE */
+
+#if defined(CORE_TEST_SERVICES)
+  (void *)svc_tfm_core_test,
+  (void *)svc_tfm_core_test_multiple_calls,
+#endif /* CORE_TEST_SERVICES */
+
+//(void *)user_function1,
+// ...
+};
+
+/* Struct FILE is implemented in stdio.h. Used to redirect printf to UART0 */
+FILE __stdout;
+/* Redirects armclang printf to UART */
+int fputc(int ch, FILE *f) {
+    /* Send byte to UART0 */
+    (void)Driver_USART0.Send((const unsigned char *)&ch, 1);
+    /* Return character written */
+    return ch;
+}
+/* redirects gcc printf to uart */
+int _write(int fd, char * str, int len)
+{
+    (void)Driver_USART0.Send(str, len);
+
+    return len;
+}
+
+/**
+ * \brief List of RTOS thread attributes
+ */
+#ifdef TEST_FRAMEWORK_NS
+static const osThreadAttr_t tserv_test = {
+    .name = "test_app",
+    .stack_size = 1024U
+};
+#endif
+
+/**
+ * \brief Static globals to hold RTOS related quantities,
+ *        main thread
+ */
+static osStatus_t   status;
+static osThreadId_t thread_id;
+
+/**
+ * \brief main() function
+ */
+__attribute__((noreturn))
+int main(void)
+{
+    (void)Driver_USART0.Initialize(NULL); /* Use UART0 as stdout */
+    Driver_USART0.Control(ARM_USART_MODE_ASYNCHRONOUS, 115200);
+
+    status = osKernelInitialize();
+
+    /* Initialize the TFM NS lock */
+    tfm_ns_lock_init();
+
+#ifdef TEST_FRAMEWORK_NS
+    thread_id = osThreadNew(test_app, NULL, &tserv_test);
+#else
+    UNUSED_VARIABLE(thread_id);
+#endif
+
+    status = osKernelStart();
+
+    /* Reached only in case of error */
+    for (;;) {
+    }
+}
diff --git a/app/os_wrapper_rtx.c b/app/os_wrapper_rtx.c
new file mode 100644
index 0000000..7d8d6d1
--- /dev/null
+++ b/app/os_wrapper_rtx.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "test/suites/sst/non_secure/os_wrapper.h"
+
+#include <string.h>
+#include "cmsis.h"
+#include "cmsis_os2.h"
+
+/* This is an example OS abstraction layer rtx RTOS for non-secure test
+ * environment */
+
+uint32_t os_wrapper_new_thread(const char* name, uint32_t stack_size,
+                               os_wrapper_thread_func func, uint32_t priority)
+{
+    osThreadAttr_t task_attribs = {.tz_module = 1};
+    osThreadId_t thread_id;
+
+    task_attribs.stack_size = stack_size;
+    task_attribs.name = name;
+    task_attribs.priority = priority;
+
+    thread_id = osThreadNew(func, NULL, &task_attribs);
+    if (thread_id == NULL) {
+        return OS_WRAPPER_ERROR;
+    }
+
+    return (uint32_t)thread_id;
+}
+
+
+uint32_t os_wrapper_semaphore_create(uint32_t max_count, uint32_t initial_count,
+                                     const char* name)
+{
+    osSemaphoreAttr_t sema_attrib = {0};
+    osSemaphoreId_t semaphore;
+
+    sema_attrib.name = name;
+
+    semaphore = osSemaphoreNew(max_count, initial_count, &sema_attrib);
+    if (semaphore == NULL) {
+        return OS_WRAPPER_ERROR;
+    }
+
+    return (uint32_t)semaphore;
+}
+
+uint32_t os_wrapper_semaphore_acquire(uint32_t semaphore_id, uint32_t timeout)
+{
+    osStatus_t status;
+
+    status = osSemaphoreAcquire((osSemaphoreId_t)semaphore_id, timeout);
+    if (status != osOK) {
+        return OS_WRAPPER_ERROR;
+    }
+
+    return 0;
+}
+
+uint32_t os_wrapper_semaphore_release(uint32_t sema)
+{
+    osStatus_t status;
+
+    status = osSemaphoreRelease((osSemaphoreId_t)sema);
+    if (status != osOK) {
+        return OS_WRAPPER_ERROR;
+    }
+
+    return 0;
+}
+
+uint32_t os_wrapper_semaphore_delete(uint32_t sema)
+{
+    osStatus_t status;
+
+    status = osSemaphoreDelete((osSemaphoreId_t)sema);
+    if (status != osOK) {
+        return OS_WRAPPER_ERROR;
+    }
+
+    return 0;
+}
+
+uint32_t os_wrapper_get_thread_id(void)
+{
+    osThreadId_t thread_id;
+
+    thread_id = osThreadGetId();
+    if(thread_id == NULL) {
+        return OS_WRAPPER_ERROR;
+    }
+
+    return (uint32_t)thread_id;
+}
+
+uint32_t os_wrapper_get_thread_priority(uint32_t id)
+{
+    osPriority_t prio;
+
+    prio = osThreadGetPriority((osThreadId_t)id);
+    if (prio == osPriorityError) {
+        return OS_WRAPPER_ERROR;
+    }
+
+    return prio;
+}
+
+uint32_t os_wrapper_delete_thread(uint32_t id)
+{
+    /* Make sure the thread has ended at this point*/
+    (void)osThreadJoin((osThreadId_t) id);
+
+    /* RTX handles thread deletion automatically. So, any
+     * action is required in this function to delete the thread. */
+
+    return 0;
+}
diff --git a/app/tfm_integ_test.c b/app/tfm_integ_test.c
new file mode 100644
index 0000000..dfa73c1
--- /dev/null
+++ b/app/tfm_integ_test.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "cmsis.h"
+#include "tfm_api.h"
+#include "cmsis_os2.h"
+
+#include "tfm_integ_test.h"
+#include "test/framework/integ_test.h"
+
+#ifdef CORE_TEST_INTERACTIVE
+#include "test/test_services/tfm_core_test/core_test_defs.h"
+#include "test/test_services/tfm_core_test/tfm_ss_core_test_veneers.h"
+#include "tfm_ns_svc.h"
+
+#define TRY_SFN(fn, ...) \
+    do { \
+        enum tfm_status_e res = (enum tfm_status_e) fn(__VA_ARGS__); \
+        switch(res) { \
+            case TFM_SUCCESS: \
+                LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") successful!!"); \
+                break; \
+            case TFM_SERVICE_PENDED: \
+                LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") pended!!"); \
+                break; \
+            case TFM_ERROR_SERVICE_ALREADY_PENDED: \
+                LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") failed, already pended!!"); \
+                break; \
+            case TFM_ERROR_SECURE_DOMAIN_LOCKED: \
+                LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") failed, S domain locked!!"); \
+                break; \
+            case TFM_ERROR_NS_THREAD_MODE_CALL: \
+                LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") failed, NS thread mode!!"); \
+                break; \
+            default: \
+                LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") failed, generic!!"); \
+        } \
+    } while(0)
+/**
+ * \brief SVC_SECURE_DECREMENT_NS_LOCK_1
+ *
+ */
+void svc_secure_decrement_ns_lock_1(void)
+{
+    TRY_SFN(tfm_core_test_sfn, CORE_TEST_ID_BLOCK, 0x1, 0x1, 0x1);
+}
+
+/**
+ * \brief SVC_SECURE_DECREMENT_NS_LOCK_2
+ *
+ */
+void svc_secure_decrement_ns_lock_2(void)
+{
+    TRY_SFN(tfm_core_test_sfn, CORE_TEST_ID_BLOCK, 0x2, 0x2, 0x2);
+}
+/**
+ * \brief Test definition for the RTX - TFM integration tests
+ *        scenarios
+ */
+enum test_type {
+    TEST_TYPE_1 = 1, /*!< Sequential test: single task using the NS lock to access TFM */
+    TEST_TYPE_2,     /*!< Priority test: high priority tries to preempt TFM, gets delayed */
+    TEST_TYPE_3,     /*!< Priority inversion: classical scenario with high priority task
+                          waiting on lower priority task undefinitely if NS lock is configured
+                          without priority inheritance */
+    TEST_TYPE_4,     /*!< non-NS lock: like sequential, but doesn't use any NS lock mechanism */
+    TEST_TYPE_5      /*!< non-NS lock, core locked: high priority tries to overcome the NS lock
+                          but finds TFM core locked by lower priority task and fails */
+};
+
+static const osThreadAttr_t tattr_seq = {
+    .name = "seq_task",
+    .stack_size = 1024U,
+    .attr_bits = osThreadJoinable,
+    .tz_module = 1,
+};
+static const osThreadAttr_t tattr_mid = {
+    .name = "mid_task",
+    .stack_size = 512U,
+    .attr_bits = osThreadJoinable,
+    .tz_module = 0,
+    .priority = osPriorityAboveNormal
+};
+static const osThreadAttr_t tattr_pri = {
+    .name = "pri_task",
+    .stack_size = 1024U,
+    .attr_bits = osThreadJoinable,
+    .tz_module = 1,
+    .priority = osPriorityHigh
+};
+
+/**
+ * \brief Mutex id, NS lock
+ */
+static osMutexId_t  mutex_id;
+
+/**
+ * \brief Mutex properties, NS lock
+ */
+static const osMutexAttr_t mattr_ns_lock = {
+    .name = "ns_lock",
+    //.attr_bits = osMutexPrioInherit
+};
+
+/**
+ * \brief SVC dispatcher
+ */
+__attribute__((always_inline)) __STATIC_INLINE void svc_dispatch(enum tfm_svc_num svc_num)
+{
+    switch (svc_num) {
+    case SVC_SECURE_DECREMENT_NS_LOCK_1:
+        SVC(SVC_SECURE_DECREMENT_NS_LOCK_1);
+        break;
+    case SVC_SECURE_DECREMENT_NS_LOCK_2:
+        SVC(SVC_SECURE_DECREMENT_NS_LOCK_2);
+        break;
+    default:
+        break;
+    }
+}
+
+/**
+ * \brief tfm_service_request
+ *
+ * \details This function is used to request a TFM
+ *          service in handler mode, using SVC.
+ *          Optionally uses the NS lock
+ */
+static void tfm_service_request(enum tfm_svc_num svc_num, bool use_ns_lock)
+{
+    osStatus_t result;
+
+    char buffer[80];
+
+#define LOG_MSG_THREAD(MSG_THREAD) \
+    do { \
+        sprintf(buffer,"%s [%s]", MSG_THREAD, osThreadGetName(osThreadGetId())); \
+        LOG_MSG(buffer); \
+    } \
+    while(0)
+
+    LOG_MSG_THREAD("Trying to acquire the TFM core from NS");
+
+    if (use_ns_lock) {
+        result = osMutexAcquire(mutex_id,0);
+        if (result == osOK) {
+            LOG_MSG_THREAD("NS Lock: acquired");
+            svc_dispatch(svc_num);
+            LOG_MSG_THREAD("NS Lock: releasing...");
+            osMutexRelease(mutex_id);
+        }
+        else {
+            LOG_MSG_THREAD("Failed to acquire the NS lock");
+
+            osMutexAcquire(mutex_id,osWaitForever);
+            LOG_MSG_THREAD("NS Lock: acquired");
+            svc_dispatch(svc_num);
+            LOG_MSG_THREAD("NS Lock: releasing...");
+            osMutexRelease(mutex_id);
+        }
+    }
+    else {
+        svc_dispatch(svc_num);
+    }
+}
+
+/**
+ * \brief Non-blocking test thread
+ *
+ */
+__attribute__((noreturn))
+static void mid_task(void *argument)
+{
+    osThreadId_t thread_id_pri;
+    osThreadState_t thread_pri_state;
+    uint32_t idx;
+
+    thread_id_pri = *((osThreadId_t *)argument);
+
+    /* go to sleep */
+    osDelay(100U);
+
+    thread_pri_state = osThreadGetState(thread_id_pri);
+
+    if (thread_pri_state == osThreadBlocked) {
+        LOG_MSG("Running [mid_task] while [pri_task] is blocked");
+    }
+    else if (thread_pri_state == osThreadTerminated) {
+        LOG_MSG("Running [mid_task] while [pri_task] is terminated");
+    }
+    else {
+        LOG_MSG("Running [mid_task]");
+    }
+
+    /* Do non TFM related, non blocking, operations */
+    for (idx=0; idx<0x3ffffff; idx++) {
+    }
+
+    LOG_MSG("Exiting [mid_task]");
+
+    osThreadExit();
+}
+
+/**
+ * \brief Priority test thread
+ *
+ */
+__attribute__((noreturn))
+static void pri_task(void *argument)
+{
+    /* go to sleep */
+    osDelay(100U);
+
+    /* After wake up, try to get hold of the NS lock */
+    tfm_service_request(SVC_SECURE_DECREMENT_NS_LOCK_2, *((bool *)argument));
+
+    osThreadExit();
+}
+
+/**
+ * \brief Sequential test thread
+ *
+ */
+__attribute__((noreturn))
+static void seq_task(void *argument)
+{
+    osThreadId_t thread_id, thread_id_mid;
+    bool use_ns_lock, use_ns_lock_pri;
+    enum test_type test_type;
+
+    test_type = *((enum test_type *)argument);
+
+    if (test_type == TEST_TYPE_1) {
+        LOG_MSG("Scenario 1 - Sequential");
+        use_ns_lock = true;
+    }
+    else if (test_type == TEST_TYPE_2) {
+        LOG_MSG("Scenario 2 - Priority");
+        use_ns_lock = true;
+        use_ns_lock_pri = true;
+        thread_id = osThreadNew(pri_task, &use_ns_lock_pri, &tattr_pri);
+    }
+    else if (test_type == TEST_TYPE_3) {
+        LOG_MSG("Scenario 3 - Priority inversion");
+        use_ns_lock = true;
+        use_ns_lock_pri = true;
+        thread_id = osThreadNew(pri_task, &use_ns_lock_pri, &tattr_pri);
+        thread_id_mid = osThreadNew(mid_task, &thread_id, &tattr_mid);
+    }
+    else if (test_type == TEST_TYPE_4) {
+        LOG_MSG("Scenario 4 - non-NS lock");
+        use_ns_lock = false;
+    }
+    else if (test_type == TEST_TYPE_5) {
+        LOG_MSG("Scenario 5 - non-NS lock, core locked");
+        use_ns_lock = true;
+        use_ns_lock_pri = false;
+        thread_id = osThreadNew(pri_task, &use_ns_lock_pri, &tattr_pri);
+    }
+    else {
+        LOG_MSG("Scenario not supported");
+        osThreadExit();
+    }
+
+    /* Try to acquire the NS lock */
+    tfm_service_request(SVC_SECURE_DECREMENT_NS_LOCK_1, use_ns_lock);
+
+    if (test_type == TEST_TYPE_1) {
+        LOG_MSG("Scenario 1 - test finished\n");
+    }
+    else if (test_type == TEST_TYPE_2) {
+        osThreadJoin(thread_id);
+        LOG_MSG("Scenario 2 - test finished\n");
+    }
+    else if (test_type == TEST_TYPE_3) {
+        osThreadJoin(thread_id);
+        osThreadJoin(thread_id_mid);
+        LOG_MSG("Scenario 3 - test finished\n");
+    }
+    else if (test_type == TEST_TYPE_4) {
+        LOG_MSG("Scenario 4 - test finished\n");
+    }
+    else if (test_type == TEST_TYPE_5) {
+        osThreadJoin(thread_id);
+        LOG_MSG("Scenario 5 - test finished\n");
+    }
+
+    osThreadExit();
+}
+
+/**
+ * \brief Execute the interactive tets cases
+ *
+ */
+void execute_ns_interactive_tests(void)
+{
+    uint8_t idx;
+
+    osThreadId_t thread_id;
+
+    /* Test type list */
+    enum test_type test_type[] = {TEST_TYPE_1, TEST_TYPE_2, TEST_TYPE_3, TEST_TYPE_4, TEST_TYPE_5};
+
+    /* Create the NS lock -- shared among testing scenarios */
+    mutex_id = osMutexNew(&mattr_ns_lock);
+
+    /* Loop in the test list */
+    for (idx=0; idx<sizeof(test_type); idx++) {
+        /* Spawn the main thread */
+        thread_id = osThreadNew(seq_task, &test_type[idx], &tattr_seq);
+
+        /* Wait for it to finish before moving to the next scenario */
+        osThreadJoin(thread_id);
+    }
+}
+#endif /* CORE_TEST_INTERACTIVE */
+
+#ifdef TEST_FRAMEWORK_NS
+/**
+ * \brief Services test thread
+ *
+ */
+__attribute__((noreturn))
+void test_app(void *argument)
+{
+    UNUSED_VARIABLE(argument);
+    start_integ_test();
+    /* End of test */
+    for (;;) {
+    }
+}
+#endif /* TEST_FRAMEWORK_NS */
diff --git a/app/tfm_integ_test.h b/app/tfm_integ_test.h
new file mode 100644
index 0000000..5be104b
--- /dev/null
+++ b/app/tfm_integ_test.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdio.h>
+#include <cmsis_compiler.h>
+
+#ifndef __TFM_INTEG_TEST_H__
+#define __TFM_INTEG_TEST_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Avoids the semihosting issue */
+#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+__asm("  .global __ARM_use_no_argv\n");
+#endif
+
+/**
+ * \brief Simple macro to mark UNUSED variables
+ *
+ */
+#define UNUSED_VARIABLE(X) ((void)(X))
+
+/**
+ * \brief Declarations for User defined SVC functions
+ *        used in CORE_TEST_INTERACTIVE or
+ *        CORE_TEST_POSITIVE
+ *
+ */
+void svc_secure_decrement_ns_lock_1(void);
+void svc_secure_decrement_ns_lock_2(void);
+
+#ifdef TEST_FRAMEWORK_NS
+/**
+ * \brief Main test application for the RTX-TFM core
+ *        integration tests
+ *
+ */
+void test_app(void *argument);
+#endif /* TEST_FRAMEWORK_NS */
+
+/**
+ * \brief Execute the interactive test cases (button push)
+ *
+ */
+void execute_ns_interactive_tests(void);
+
+/**
+ * \brief Logging function
+ *
+ */
+__attribute__((always_inline)) __STATIC_INLINE void LOG_MSG(const char *MSG)
+{
+#ifndef LOG_MSG_HANDLER_MODE_PRINTF_ENABLED
+    /* if IPSR is non-zero, exception is active. NOT banked S/NS */
+    if (!__get_IPSR()) {
+        printf("\t\e[1;32m[Non-Sec] %s\e[0m\r\n", MSG);
+    }
+#else
+    printf("\t\e[1;32m[Non-Sec] %s\e[0m\r\n", MSG);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TFM_INTEG_TEST_H__ */